Skip to content
This repository has been archived by the owner on Jul 1, 2022. It is now read-only.

Commit

Permalink
Fixed a retain cycle related to Dispatch After
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexLittlejohn committed Apr 10, 2017
1 parent 159acf3 commit c348b43
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 60 deletions.
16 changes: 11 additions & 5 deletions ALCameraViewController/Utilities/ImageFetcher.swift
Expand Up @@ -12,6 +12,12 @@ import Photos
public typealias ImageFetcherSuccess = (PHFetchResult<PHAsset>) -> ()
public typealias ImageFetcherFailure = (NSError) -> ()

//extension PHFetchResult: Sequence {
// public func makeIterator() -> NSFastEnumerationIterator {
// return NSFastEnumerationIterator(self)
// }
//}

public class ImageFetcher {

private var success: ImageFetcherSuccess?
Expand All @@ -35,11 +41,11 @@ public class ImageFetcher {
}

public func fetch() -> Self {
_ = PhotoLibraryAuthorizer { [weak self] error in
_ = PhotoLibraryAuthorizer { error in
if error == nil {
self?.onAuthorized()
self.onAuthorized()
} else {
self?.failure?(error!)
self.failure?(error!)
}
}
return self
Expand All @@ -50,8 +56,8 @@ public class ImageFetcher {
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
libraryQueue.async {
let assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
DispatchQueue.main.async { [weak self] in
self?.success?(assets)
DispatchQueue.main.async {
self.success?(assets)
}
}
}
Expand Down
13 changes: 4 additions & 9 deletions ALCameraViewController/Utilities/PhotoLibraryAuthorizer.swift
Expand Up @@ -33,18 +33,13 @@ class PhotoLibraryAuthorizer {
PHPhotoLibrary.requestAuthorization(handleAuthorization)
break
case .authorized:
DispatchQueue.main.async { [weak self] in
self?.completion(nil)
DispatchQueue.main.async {
self.completion(nil)
}
break
case .denied, .restricted:
DispatchQueue.main.async { [weak self] in

guard let completion = self?.completion else {
return
}

self?.onDeniedOrRestricted(completion: completion)
DispatchQueue.main.async {
self.onDeniedOrRestricted(completion: self.completion)
}
break
}
Expand Down
18 changes: 8 additions & 10 deletions ALCameraViewController/Utilities/SingleImageFetcher.swift
Expand Up @@ -50,11 +50,11 @@ public class SingleImageFetcher {
}

public func fetch() -> Self {
_ = PhotoLibraryAuthorizer { [weak self] error in
_ = PhotoLibraryAuthorizer { error in
if error == nil {
self?._fetch()
self._fetch()
} else {
self?.failure?(error!)
self.failure?(error!)
}
}
return self
Expand Down Expand Up @@ -83,15 +83,13 @@ public class SingleImageFetcher {

targetSize = CGSize(width: dimension, height: dimension)
}

let domain = errorDomain

PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { [weak self] image, _ in

PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { image, _ in
if let image = image {
self?.success?(image)
self.success?(image)
} else {
let error = errorWithKey("error.cant-fetch-photo", domain: domain)
self?.failure?(error)
let error = errorWithKey("error.cant-fetch-photo", domain: self.errorDomain)
self.failure?(error)
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions ALCameraViewController/Utilities/SingleImageSaver.swift
Expand Up @@ -39,11 +39,11 @@ public class SingleImageSaver {

public func save() -> Self {

_ = PhotoLibraryAuthorizer { [weak self] error in
_ = PhotoLibraryAuthorizer { error in
if error == nil {
self?._save()
self._save()
} else {
self?.failure?(error!)
self.failure?(error!)
}
}

Expand All @@ -52,7 +52,7 @@ public class SingleImageSaver {

private func _save() {
guard let image = image else {
invokeFailure()
self.invokeFailure()
return
}

Expand All @@ -62,28 +62,28 @@ public class SingleImageSaver {
.performChanges({
let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
assetIdentifier = request.placeholderForCreatedAsset
}) { [weak self] finished, error in
}) { finished, error in

guard let assetIdentifier = assetIdentifier, finished else {
self?.invokeFailure()
self.invokeFailure()
return
}

self?.fetch(assetIdentifier)
self.fetch(assetIdentifier)
}
}

private func fetch(_ assetIdentifier: PHObjectPlaceholder) {

let assets = PHAsset.fetchAssets(withLocalIdentifiers: [assetIdentifier.localIdentifier], options: nil)

DispatchQueue.main.async { [weak self] in
DispatchQueue.main.async {
guard let asset = assets.firstObject else {
self?.invokeFailure()
self.invokeFailure()
return
}

self?.success?(asset)
self.success?(asset)
}
}

Expand Down
13 changes: 5 additions & 8 deletions ALCameraViewController/Utilities/VolumeControl.swift
Expand Up @@ -26,23 +26,20 @@ public class VolumeControl {

init(view: UIView, onVolumeChange: VolumeChangeAction?) {
self.onVolumeChange = onVolumeChange
configureInView(view)
view.addSubview(volumeView)
view.sendSubview(toBack: volumeView)

try? AVAudioSession.sharedInstance().setActive(true)
NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged), name: NSNotification.Name(rawValue: changeKey), object: nil)
}

deinit {
try? AVAudioSession.sharedInstance().setActive(false)
NotificationCenter.default.removeObserver(self)
onVolumeChange = nil
volumeView.removeFromSuperview()
}

func configureInView(_ view: UIView) {
view.addSubview(volumeView)
view.sendSubview(toBack: volumeView)
}


@objc func volumeChanged() {
guard let slider = volumeView.subviews.filter({ $0 is UISlider }).first as? UISlider else { return }
let volume = AVAudioSession.sharedInstance().outputVolume
Expand Down
18 changes: 12 additions & 6 deletions ALCameraViewController/ViewController/CameraViewController.swift
Expand Up @@ -12,7 +12,7 @@ import Photos

public typealias CameraViewCompletion = (UIImage?, PHAsset?) -> Void

open extension CameraViewController {
public extension CameraViewController {
public class func imagePickerViewController(croppingEnabled: Bool, completion: @escaping CameraViewCompletion) -> UINavigationController {
let imagePicker = PhotoLibraryViewController()
let navigationController = UINavigationController(rootViewController: imagePicker)
Expand Down Expand Up @@ -295,10 +295,12 @@ open class CameraViewController: UIViewController {
*/
override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
lastInterfaceOrientation = UIApplication.shared.statusBarOrientation

lastInterfaceOrientation = UIApplication.shared.statusBarOrientation
if animationRunning {
return
}

CATransaction.begin()
CATransaction.setDisableActions(true)
coordinator.animate(alongsideTransition: { [weak self] animation in
Expand Down Expand Up @@ -392,7 +394,7 @@ open class CameraViewController: UIViewController {
animationRunning = true

/**
* Dispach delay to avoid any conflict between the CATransaction of rotation of the screen
* Dispatch delay to avoid any conflict between the CATransaction of rotation of the screen
* and CATransaction of animation of buttons.
*/

Expand All @@ -401,7 +403,11 @@ open class CameraViewController: UIViewController {
let options = rotateAnimation

let time: DispatchTime = DispatchTime.now() + Double(1 * UInt64(NSEC_PER_SEC)/10)
DispatchQueue.main.asyncAfter(deadline: time) {
DispatchQueue.main.asyncAfter(deadline: time) { [weak self] in

guard let _ = self else {
return
}

CATransaction.begin()
CATransaction.setDisableActions(false)
Expand Down Expand Up @@ -463,7 +469,7 @@ open class CameraViewController: UIViewController {
desc = localizedString("permissions.description")
}

permissionsView.configureInView(view, title: title, descriptiom: desc, completion: close)
permissionsView.configureInView(view, title: title, description: desc, completion: { [weak self] in self?.close() })
}

/**
Expand Down Expand Up @@ -534,7 +540,7 @@ open class CameraViewController: UIViewController {
}

let image = UIImage(named: flashImage(device.flashMode),
in: Bundle(for: CameraViewController.self),
in: CameraGlobals.shared.bundle,
compatibleWith: nil)

flashButton.setImage(image, for: .normal)
Expand Down
Expand Up @@ -286,7 +286,7 @@ public class ConfirmViewController: UIViewController, UIScrollViewDelegate {

let desc = localizedString("error.cant-fetch-photo.description")

permissionsView.configureInView(view, title: error.localizedDescription, descriptiom: desc, completion: cancel)
permissionsView.configureInView(view, title: error.localizedDescription, description: desc, completion: { [weak self] in self?.cancel() })
}

}
5 changes: 0 additions & 5 deletions ALCameraViewController/Views/CropOverlay.swift
Expand Up @@ -23,11 +23,6 @@ internal class CropOverlay: UIView {
let cornerWidth: CGFloat = 20
let lineWidth: CGFloat = 1

internal init() {
super.init(frame: CGRect.zero)
createLines()
}

internal override init(frame: CGRect) {
super.init(frame: frame)
createLines()
Expand Down
4 changes: 2 additions & 2 deletions ALCameraViewController/Views/PermissionsView.swift
Expand Up @@ -29,14 +29,14 @@ internal class PermissionsView: UIView {
commonInit()
}

func configureInView(_ view: UIView, title: String, descriptiom: String, completion: @escaping ButtonAction) {
func configureInView(_ view: UIView, title: String, description: String, completion: @escaping ButtonAction) {
let closeButton = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))

view.addSubview(self)
addSubview(closeButton)

titleLabel.text = title
descriptionLabel.text = descriptiom
descriptionLabel.text = description

closeButton.action = completion
closeButton.setImage(UIImage(named: "retakeButton", in: CameraGlobals.shared.bundle, compatibleWith: nil), for: UIControlState())
Expand Down
2 changes: 1 addition & 1 deletion CameraViewController/Info.plist
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>1.2.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
6 changes: 3 additions & 3 deletions Example/ViewController.swift
Expand Up @@ -29,9 +29,9 @@ class ViewController: UIViewController {
}

@IBAction func openLibrary(_ sender: AnyObject) {
let libraryViewController = CameraViewController.imagePickerViewController(croppingEnabled: croppingEnabled) { image, asset in
self.imageView.image = image
self.dismiss(animated: true, completion: nil)
let libraryViewController = CameraViewController.imagePickerViewController(croppingEnabled: croppingEnabled) { [weak self] image, asset in
self?.imageView.image = image
self?.dismiss(animated: true, completion: nil)
}

present(libraryViewController, animated: true, completion: nil)
Expand Down

0 comments on commit c348b43

Please sign in to comment.