Swiftpack.co - Package - TimOliver/TOCropViewController
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.

TOCropViewController

CI Version Carthage compatible GitHub license Platform

TOCropViewController is an open-source UIViewController subclass to crop out sections of UIImage objects, as well as perform basic rotations. It is excellent for things like editing profile pictures, or sharing parts of a photo online. It has been designed with the iOS Photos app editor in mind, and as such, behaves in a way that should already feel familiar to users of iOS.

For Swift developers, CropViewController is a Swift wrapper that completely encapsulates TOCropViewController and provides a much more native, Swiftier interface.

Proudly powering apps by

Features

  • Crop images by dragging the edges of a grid overlay.
  • Optionally, crop circular copies of images.
  • Rotate images in 90-degree segments.
  • Clamp the crop box to a specific aspect ratio.
  • A reset button to completely undo all changes.
  • iOS 7/8 translucency to make it easier to view the cropped region.
  • The choice of having the controller return the cropped image to a delegate, or immediately pass it to a UIActivityViewController.
  • A custom animation and layout when the device is rotated to landscape mode.
  • Custom 'opening' and 'dismissal' animations.
  • Localized in 28 languages.

System Requirements

iOS 8.0 or above

Installation

CocoaPods

Objective-C

Add the following to your Podfile:

pod 'TOCropViewController'

Swift

Add the following to your Podfile:

pod 'CropViewController'
Swift Package Manager

Add the following to your Package.swift:

dependencies: [
  // ...
  .package(url: "https://github.com/TimOliver/TOCropViewController.git"),
],
Carthage
  1. Add the following to your Cartfile:
github "TimOliver/TOCropViewController"
  1. Run carthage update

  2. From the Carthage/Build folder, import one of the two frameworks into your Xcode project. For Objective-C projects, import just TOCropViewController.framework and for Swift, import CropViewController.framework instead. Each framework is separate; you do not need to import both.

  3. Follow the remaining steps on Getting Started with Carthage to finish integrating the framework.

Manual Installation

All of the necessary source and resource files for TOCropViewController are in Objective-C/TOCropViewController, and all of the necessary Swift files are in Swift/CropViewController.

For Objective-C projects, copy just the TOCropViewController directory to your Xcode project. For Swift projects, copy both TOCropViewController and CropViewController to your project.

Examples

Using TOCropViewController is very straightforward. Simply create a new instance passing the UIImage object you wish to crop, and then present it modally on the screen.

While TOCropViewController prefers to be presented modally, it can also be pushed to a UINavigationController stack.

For a complete working example, check out the sample apps included in this repo.

Basic Implementation

Swift

func presentCropViewController() {
  let image: UIImage = ... //Load an image
  
  let cropViewController = CropViewController(image: image)
  cropViewController.delegate = self
  present(cropViewController, animated: true, completion: nil)
}

func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
        // 'image' is the newly cropped version of the original image
    }

Objective-C

- (void)presentCropViewController
{
  UIImage *image = ...; // Load an image
  
  TOCropViewController *cropViewController = [[TOCropViewController alloc] initWithImage:image];
  cropViewController.delegate = self;
  [self presentViewController:cropViewController animated:YES completion:nil];
}

- (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
  // 'image' is the newly cropped version of the original image
}

Similar to many UIKit UIViewController subclasses, like MFMailComposeViewController, the class responsible for presenting view controller should also take care of dismissing it upon cancellation. To dismiss TOCropViewController, implement the cropViewController:didFinishCancelled: delegate method, and call dismissViewController:animated: from there.

Making a Circular Cropped Image

Swift

func presentCropViewController() {
    var image: UIImage? // Load an image
    let cropViewController = CropViewController(croppingStyle: .circular, image: image)
    cropViewController.delegate = self
    self.present(cropViewController, animated: true, completion: nil)
}

func cropViewController(_ cropViewController: TOCropViewController?, didCropToCircularImage image: UIImage?, with cropRect: CGRect, angle: Int) {
    // 'image' is the newly cropped, circular version of the original image
}

Objective-C

- (void)presentCropViewController
{
UIImage *image = ...; // Load an image

TOCropViewController *cropViewController = [[TOCropViewController alloc] initWithCroppingStyle:TOCropViewCroppingStyleCircular image:image];
cropViewController.delegate = self;
[self presentViewController:cropViewController animated:YES completion:nil];
}

- (void)cropViewController:(TOCropViewController *)cropViewController didCropToCircularImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
// 'image' is the newly cropped, circular version of the original image
}
Sharing Cropped Images Via a Share Sheet

Swift

func presentCropViewController() {
    var image: UIImage? // Load an image
    let cropViewController = CropViewController(image: image)
    cropViewController.showActivitySheetOnDone = true
    self.present(cropViewController, animated: true, completion: nil)
}

Objective-C

- (void)presentCropViewController
{
  UIImage *image = ...; // Load an image
  
  TOCropViewController *cropViewController = [[TOCropViewController alloc] initWithImage:image];
  cropViewController.showActivitySheetOnDone = YES;
  [self presentViewController:cropViewController animated:YES completion:nil];
}
Presenting With a Custom Animation

Optionally, TOCropViewController also supports a custom presentation animation where an already-visible copy of the image will zoom in to fill the screen.

Swift


func presentCropViewController() {
    var image: UIImage? // Load an image
    var imageView = UIImageView(image: image)
    var frame: CGRect = view.convert(imageView.frame, to: view)
    
    let cropViewController = CropViewController(image: image)
    cropViewController.delegate = self
    self.present(cropViewController, animated: true, completion: nil)
    cropViewController.presentAnimated(fromParentViewController: self, fromFrame: frame, completion: nil)
}

Objective-C

- (void)presentCropViewController
{
  UIImage *image = ...;
  UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
  CGRect frame = [self.view convertRect:imageView.frame toView:self.view];
  
  TOCropViewController *cropViewController = [[TOCropViewController alloc] initWithImage:image];
  cropViewController.delegate = self;
  [self presentViewController:cropViewController animated:YES completion:nil];
  [cropViewController presentAnimatedFromParentViewController:self fromFrame:frame completion:nil];
}

Architecture of TOCropViewController

While traditional cropping UI implementations will usually just have a dimming view with a square hole cut out of the middle, TOCropViewController goes about its implementation a little differently.

Since there are two views that are overlaid over the image (A dimming view and a translucency view), trying to cut a hole open in both of them would be rather complex. Instead, an image view is placed in a scroll view in the background, and a copy of the image view is placed on top, inside a container view that is clipped to the designated cropping size. The size and position of the foreground image is then made to match the background view, creating the illusion that there is a hole in the dimming views, and minimising the number of views onscreen.

Credits

TOCropViewController was originally created by Tim Oliver as a component for iComics, a comic reader app for iOS.

Thanks also goes to TOCropViewController's growing list of contributors!

iOS Device mockups used in the screenshot created by Pixeden.

License

TOCropViewController is licensed under the MIT License, please see the LICENSE file. analytics

Github

link
Stars: 3844

Releases

v2.6.0 - 2020-12-29T16:46:20

Added

  • Extremely basic support for Mac Catalyst, with an accompanying sample app. (#464)
  • Switched to using system SF Symbol icons on iOS 13.0 and up. (#455)
  • doneButtonColor and cancelButtonColor properties to control the color of the main call-to-action buttons in the toolbar. (#436)
  • showOnlyIcons property to disable showing the "Cancel" and "Done" text labels. (#438)
  • commitCurrentCrop() method to programmatically simulate tapping the 'Done' button. (#441)
  • Added Catalan localization. (#449)

Fixed

  • Fixed an issue where visible snapping would occur during the presentation animation on iPad models with rounded corners. (#461)
  • Improved logic for detecting whether the controller needs to be popped or dismissed from its current presentation context. (#443)
  • Fixed a CocoaPods installation issue where warnings would be displayed about importing the header references needed for SPM support. (#445)
  • Added provisions for later versions of SPM no longer supporting iOS 8. (#448)
  • Added allowedAspectRatios property to Swift layer. (#453)

Enhancements

  • Added back in resource support for SPM on Xcode 12. (#466)
  • Fixed a potential performance slow-down by replacing a custom mask, with standard CALAyer rounded corners for circular crops. (#462)
  • Rewrote how rotated regions of an image are extracted to not rely on Core Animation hackery. (#463)

v2.5.5 - 2020-09-30T16:20:48

Fixed

  • Duplicate header build warnings when installing via CocoaPods. (#432)

v2.5.4 - 2020-07-20T07:18:30

Fixed

  • Various fixes and improvements to SPM support. (#417 #422)

v2.5.3 - 2020-06-11T06:34:46

Added

  • SPM Support. (#413)
  • The ability to explicitly show and hide the 'Cancel' and 'Done' buttons in the toolbar. (#392)

Fixed

  • A memory crash caused by improper self usage in delegates between multiple instances of the Swift crop view controller. (#409)

v2.5.2 - 2019-10-22T15:00:17

Added

  • Brazilian Portuguese Language Support (#380)

Fixed

  • A visual glitch that would occur in iOS 13 because the Swift view controller wasn't explicitly marked as full screen. (#385)
  • A visual glitch where the image would snap upwards during the presentation animation on non-Face ID devices. (#387)
  • A bug where subclassing the class in Swift would fail because it wasn't using the desginated initializer. (#379)

v2.5.1 - 2019-07-07T15:28:38

Added

  • Finnish Language Support (#360)

Enhancements

  • Improved the UX of the cancellation dialog by changing the buttons from affirmative actions to explicit actions. (#362)

Fixed

  • A crash that would occur if the cancellation confirmation dialog was attempted to be displayed on iPad. (#362)

v2.5.0 - 2019-04-21T10:59:34

Added

  • Swift 5.0 Support (#343)
  • Persian Language Support (#337)
  • Added customAspectRatioName property to expose the custom aspect ratio as a selectable choice (#344)

Fixed

  • Made delegate in CropViewController weak. (#338)

v2.4.0 - 2019-03-19T16:48:05

Added

  • Swift 4.2 Support
  • Romanian and Hungarian localizations
  • The ability to show only certain aspect ratios
  • A setting to allow confirmation before cancelling a crop

Fixed

  • Fixed layout issue on the new iPad Pro
  • Fixed issues with the aspect ratio settings when zooming out
  • Fixed an issue when rotating images would sometimes break
  • A bug where the completion handler of the cropping operation wouldn't fire

Removed

  • iOS 7 Support

- 2018-07-24T01:34:08

Added

  • minimumAspectRatio to set a minimum shape that the cropping box can be scaled to.
  • cropViewPadding to specifically control how much padding from the edge the crop box gives.
  • cropAdjustingDelay to specifically control how long the timer waits until animating the crop transition.
  • aspectRatioLockDimensionSwapEnabled as a stopgap to locking the aspect ratio when rotating the image.

Fixed

  • More thorough sanitation of the final frame calculation.
  • A bug where sometimes the square aspect ratio would stop being square.
  • A memory cycle leak in the Swift wrapper.
  • A broken animation when rotating the device orientation 180 degrees.
  • A broken animation if you hit 'reset' right after resizing the crop box.
  • Danish and Malaysian localisations weren't being imported properly.

- 2017-11-16T15:37:47

Added

  • Support for iPhone X.

Changed

  • Fixed missing semicolons in iOS 7 code brace.
  • Fixed minor issue with certain nullable properties being marked as nonnull.
  • Made the clockwise rotation button visible by default.

Fixed

  • Broken rotation animations in iOS 11.
  • Incorrect inset of crop content when status bar is visible.
  • General cleanup of the codebase

- 2017-09-07T06:15:38

2.1.0 - 2017-09-07

Added

  • Added a CHANGELOG. (Yay!)
  • TOCropViewController.title property will display a title label above the crop view box.
  • Added more thorough checks to ensure both all delegate and completion block handlers execute in the right order.

Changed

  • Fixed scroll view insets to work properly with new iOS 11 assumptions.
  • Fixed crop box frame resizing to properly clamp when it touches an outer boundary.