From e6cf9c5e6fe09053475c678b0359cf35fb0c3b92 Mon Sep 17 00:00:00 2001 From: Vinnie Hesener Date: Sat, 29 Sep 2018 10:13:52 -0500 Subject: [PATCH] Modernizing for Swift 4.2 (#46) Support Swift 4.2 --- Closures.podspec.json | 23 +++++++++ Xcode/Closures.xcodeproj/project.pbxproj | 12 +++-- Xcode/Closures/Source/UIBarButtonItem.swift | 8 ++-- Xcode/Closures/Source/UIControl.swift | 48 +++++++++---------- .../Closures/Source/UIGestureRecognizer.swift | 4 +- .../Source/UIImagePickerController.swift | 25 +++++----- Xcode/Closures/Source/UITableView.swift | 14 +++--- Xcode/ClosuresTests/UIControlTests.swift | 17 ------- 8 files changed, 80 insertions(+), 71 deletions(-) create mode 100644 Closures.podspec.json diff --git a/Closures.podspec.json b/Closures.podspec.json new file mode 100644 index 0000000..c8ea821 --- /dev/null +++ b/Closures.podspec.json @@ -0,0 +1,23 @@ +{ + "name": "Closures", + "version": "0.4", + "summary": "Swifty closures for UIKit and Foundation", + "homepage": "https://github.com/vhesener/Closures", + "screenshots": [ + "https://raw.githubusercontent.com/vhesener/Closures/assets/assets/playground_general.gif", + "https://raw.githubusercontent.com/vhesener/Closures/assets/assets/reference_large.png" + ], + "license": "MIT", + "authors": "Vinnie Hesener", + "platforms": { + "ios": "9.0" + }, + "source": { + "git": "https://github.com/vhesener/Closures.git", + "tag": "v0.4" + }, + "source_files": "Xcode/Closures/Source", + "documentation_url": "https://vhesener.github.io/Closures/", + "description": "Closures is an iOS Framework that adds closure handlers to many of the popular\nUIKit and Foundation classes. Although this framework is a substitute for \nsome Cocoa Touch design patterns, such as Delegation and Data Sources, and \nTarget-Action, the authors make no claim regarding which is a better way to \naccomplish the same type of task. Most of the time it is a matter of style, \npreference, or convenience that will determine if any of these closure extensions \nare beneficial.\n\nWhether you’re a functional purist, dislike a particular API, or simply just \nwant to organize your code a little bit, you might enjoy using this library.", + "pushed_with_swift_version": "4.2" +} diff --git a/Xcode/Closures.xcodeproj/project.pbxproj b/Xcode/Closures.xcodeproj/project.pbxproj index 8d7447e..49a9dd1 100644 --- a/Xcode/Closures.xcodeproj/project.pbxproj +++ b/Xcode/Closures.xcodeproj/project.pbxproj @@ -212,7 +212,7 @@ }; 3F7620E61D849B5000E17BF5 = { CreatedOnToolsVersion = 8.0; - LastSwiftMigration = 0900; + LastSwiftMigration = ""; ProvisioningStyle = Automatic; }; }; @@ -354,6 +354,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -410,6 +411,7 @@ SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -436,7 +438,7 @@ SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -458,7 +460,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -471,7 +473,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.vhesener.ClosuresTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -484,7 +486,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.vhesener.ClosuresTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Xcode/Closures/Source/UIBarButtonItem.swift b/Xcode/Closures/Source/UIBarButtonItem.swift index a620791..9a0f1c4 100644 --- a/Xcode/Closures/Source/UIBarButtonItem.swift +++ b/Xcode/Closures/Source/UIBarButtonItem.swift @@ -33,7 +33,7 @@ public extension UIBarButtonItem { * parameter style: The `UIBarButtonItemStyle` of the button * parameter handler: The closure that is called when the button is tapped */ - public convenience init(image: UIImage?, style: UIBarButtonItemStyle, handler: @escaping () -> Void) { + public convenience init(image: UIImage?, style: UIBarButtonItem.Style, handler: @escaping () -> Void) { self.init(image: image, style: style, target: nil, action: nil) onTap(handler: handler) } @@ -49,7 +49,7 @@ public extension UIBarButtonItem { * parameter handler: The closure that is called when the button is tapped */ @available(iOS 5.0, *) - public convenience init(image: UIImage?, landscapeImagePhone: UIImage?, style: UIBarButtonItemStyle, handler: @escaping () -> Void) { + public convenience init(image: UIImage?, landscapeImagePhone: UIImage?, style: UIBarButtonItem.Style, handler: @escaping () -> Void) { self.init(image: image, landscapeImagePhone: landscapeImagePhone, style: style, target: nil, action: nil) onTap(handler: handler) } @@ -63,7 +63,7 @@ public extension UIBarButtonItem { * parameter style: The `UIBarButtonItemStyle` of the button * parameter handler: The closure that is called when the button is tapped */ - public convenience init(title: String?, style: UIBarButtonItemStyle, handler: @escaping () -> Void) { + public convenience init(title: String?, style: UIBarButtonItem.Style, handler: @escaping () -> Void) { self.init(title: title, style: style, target: nil, action: nil) onTap(handler: handler) } @@ -76,7 +76,7 @@ public extension UIBarButtonItem { * parameter barButtonSystemItem: The `UIBarButtonSystemItem` to be used for the button * parameter handler: The closure that is called when the button is tapped */ - public convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, handler: @escaping () -> Void) { + public convenience init(barButtonSystemItem systemItem: UIBarButtonItem.SystemItem, handler: @escaping () -> Void) { self.init(barButtonSystemItem: systemItem, target: nil, action: nil) onTap(handler: handler) } diff --git a/Xcode/Closures/Source/UIControl.swift b/Xcode/Closures/Source/UIControl.swift index be598f5..0fb831a 100644 --- a/Xcode/Closures/Source/UIControl.swift +++ b/Xcode/Closures/Source/UIControl.swift @@ -56,7 +56,7 @@ extension UIControl { * returns: itself so you can daisy chain the other event handler calls */ @discardableResult - public func on(_ events: UIControlEvents, handler: @escaping EventHandler) -> Self { + public func on(_ events: UIControl.Event, handler: @escaping EventHandler) -> Self { guard let selector = selectorSignature(for: events) else { return self } @@ -147,7 +147,7 @@ extension UIControl { * parameter type: The UIControlEvents option to listen for */ - private func trigger(_ sender: UIControl, _ event: UIEvent?, for type: UIControlEvents) { + private func trigger(_ sender: UIControl, _ event: UIEvent?, for type: UIControl.Event) { NotificationCenter.closures.post(name: notificationName(for: type), object: self, userInfo: [UIControl.eventKey: event as Any]) @@ -161,7 +161,7 @@ extension UIControl { * returns: An identifyable Notification.Name */ - private func notificationName(for events: UIControlEvents) -> Notification.Name { + private func notificationName(for events: UIControl.Event) -> Notification.Name { return Notification.Name("\(String.namespace).notifications.names.UIControlTargetAction.\(events)") } } @@ -175,47 +175,47 @@ extension UIControl { * returns: The selector */ - fileprivate func selectorSignature(for event: UIControlEvents) -> Selector? { + fileprivate func selectorSignature(for event: UIControl.Event) -> Selector? { switch event { - case UIControlEvents.touchDown: + case UIControl.Event.touchDown: return #selector(touchDown(sender:event:)) - case UIControlEvents.touchDownRepeat: + case UIControl.Event.touchDownRepeat: return #selector(touchDownRepeat(sender:event:)) - case UIControlEvents.touchDragInside: + case UIControl.Event.touchDragInside: return #selector(touchDragInside(sender:event:)) - case UIControlEvents.touchDragOutside: + case UIControl.Event.touchDragOutside: return #selector(touchDragOutside(sender:event:)) - case UIControlEvents.touchDragEnter: + case UIControl.Event.touchDragEnter: return #selector(touchDragEnter(sender:event:)) - case UIControlEvents.touchDragExit: + case UIControl.Event.touchDragExit: return #selector(touchDragExit(sender:event:)) - case UIControlEvents.touchUpInside: + case UIControl.Event.touchUpInside: return #selector(touchUpInside(sender:event:)) - case UIControlEvents.touchUpOutside: + case UIControl.Event.touchUpOutside: return #selector(touchUpOutside(sender:event:)) - case UIControlEvents.touchCancel: + case UIControl.Event.touchCancel: return #selector(touchCancel(sender:event:)) - case UIControlEvents.valueChanged: + case UIControl.Event.valueChanged: return #selector(valueChanged(sender:event:)) - case UIControlEvents.primaryActionTriggered: + case UIControl.Event.primaryActionTriggered: return #selector(primaryActionTriggered(sender:event:)) - case UIControlEvents.editingDidBegin: + case UIControl.Event.editingDidBegin: return #selector(editingDidBegin(sender:event:)) - case UIControlEvents.editingChanged: + case UIControl.Event.editingChanged: return #selector(editingChanged(sender:event:)) - case UIControlEvents.editingDidEnd: + case UIControl.Event.editingDidEnd: return #selector(editingDidEnd(sender:event:)) - case UIControlEvents.editingDidEndOnExit: + case UIControl.Event.editingDidEndOnExit: return #selector(editingDidEndOnExit(sender:event:)) - case UIControlEvents.allTouchEvents: + case UIControl.Event.allTouchEvents: return #selector(allTouchEvents(sender:event:)) - case UIControlEvents.allEditingEvents: + case UIControl.Event.allEditingEvents: return #selector(allEditingEvents(sender:event:)) - case UIControlEvents.applicationReserved: + case UIControl.Event.applicationReserved: return #selector(applicationReserved(sender:event:)) - case UIControlEvents.systemReserved: + case UIControl.Event.systemReserved: return #selector(systemReserved(sender:event:)) - case UIControlEvents.allEvents: + case UIControl.Event.allEvents: return #selector(allEvents(sender:event:)) default: return nil diff --git a/Xcode/Closures/Source/UIGestureRecognizer.swift b/Xcode/Closures/Source/UIGestureRecognizer.swift index 858f826..75705bb 100644 --- a/Xcode/Closures/Source/UIGestureRecognizer.swift +++ b/Xcode/Closures/Source/UIGestureRecognizer.swift @@ -198,7 +198,7 @@ extension UISwipeGestureRecognizer { * parameter touchesRequired: Defaults UISwipeGestureRecognizer's `numberOfTouchesRequired` property value * parameter handler: The closure that is called when the gesture is recognized */ - public convenience init(direction: UISwipeGestureRecognizerDirection = .right, + public convenience init(direction: UISwipeGestureRecognizer.Direction = .right, touchesRequired: Int = 1, handler: @escaping (_ gesture: UISwipeGestureRecognizer) -> Void) { self.init() @@ -221,7 +221,7 @@ extension UIView { customizations */ @discardableResult - public func addSwipeGesture(direction: UISwipeGestureRecognizerDirection = .right, + public func addSwipeGesture(direction: UISwipeGestureRecognizer.Direction = .right, touchesRequired: Int = 1, handler: @escaping (_ gesture: UISwipeGestureRecognizer) -> Void) -> UISwipeGestureRecognizer { let gesture = UISwipeGestureRecognizer(direction: direction, diff --git a/Xcode/Closures/Source/UIImagePickerController.swift b/Xcode/Closures/Source/UIImagePickerController.swift index 82cf4f2..62e38f4 100644 --- a/Xcode/Closures/Source/UIImagePickerController.swift +++ b/Xcode/Closures/Source/UIImagePickerController.swift @@ -25,9 +25,10 @@ import PhotosUI fileprivate final class ImagePickerControllerDelegate: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, DelegateProtocol { static var delegates = Set>() - fileprivate var didFinishPickingMedia: ((_ withInfo: [String: Any]) -> Void)? + fileprivate var didFinishPickingMedia: ((_ withInfo: [UIImagePickerController.InfoKey: Any]) -> Void)? + fileprivate func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [String: Any]) { + didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { didFinishPickingMedia?(info) } @@ -93,7 +94,7 @@ extension UIImagePickerController { delegate call in a `Result` struct. The original Dictionary can be found in the `rawInfo` property. */ - public convenience init(source: UIImagePickerControllerSourceType = .photoLibrary, + public convenience init(source: UIImagePickerController.SourceType = .photoLibrary, allow: UIImagePickerController.MediaFilter = .image, cameraOverlay: UIView? = nil, showsCameraControls: Bool = true, @@ -178,7 +179,7 @@ extension UIImagePickerController { * returns: itself so you can daisy chain the other delegate calls */ @discardableResult - public func didFinishPickingMedia(handler: @escaping (_ withInfo: [String: Any]) -> Void) -> Self { + public func didFinishPickingMedia(handler: @escaping (_ withInfo: [UIImagePickerController.InfoKey: Any]) -> Void) -> Self { return update { $0.didFinishPickingMedia = handler } } @@ -270,7 +271,7 @@ extension UIImagePickerController { `-imagePickerController:didFinishPickingMediaWithInfo:` delegate method. */ - public let rawInfo: [String: Any] + public let rawInfo: [UIImagePickerController.InfoKey: Any] /** The type of media picked by the user, converted to a MediaFilter option. This is equivalent to the @@ -304,14 +305,14 @@ extension UIImagePickerController { */ public let metaData: NSDictionary? - init(rawInfo: [String: Any]) { + init(rawInfo: [UIImagePickerController.InfoKey: Any]) { self.rawInfo = rawInfo - type = (rawInfo[UIImagePickerControllerMediaType] as! CFString).mediaFilter - originalImage = rawInfo[UIImagePickerControllerOriginalImage] as? UIImage - editedImage = rawInfo[UIImagePickerControllerEditedImage] as? UIImage - cropRect = rawInfo[UIImagePickerControllerCropRect] as? CGRect - movieUrl = rawInfo[UIImagePickerControllerMediaURL] as? URL - metaData = rawInfo[UIImagePickerControllerMediaMetadata] as? NSDictionary + type = (rawInfo[UIImagePickerController.InfoKey.mediaType] as! CFString).mediaFilter + originalImage = rawInfo[UIImagePickerController.InfoKey.originalImage] as? UIImage + editedImage = rawInfo[UIImagePickerController.InfoKey.editedImage] as? UIImage + cropRect = rawInfo[UIImagePickerController.InfoKey.cropRect] as? CGRect + movieUrl = rawInfo[UIImagePickerController.InfoKey.mediaURL] as? URL + metaData = rawInfo[UIImagePickerController.InfoKey.mediaMetadata] as? NSDictionary } } } diff --git a/Xcode/Closures/Source/UITableView.swift b/Xcode/Closures/Source/UITableView.swift index 7e8b95d..058eca6 100644 --- a/Xcode/Closures/Source/UITableView.swift +++ b/Xcode/Closures/Source/UITableView.swift @@ -266,7 +266,7 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat fileprivate var willDeselectRowAt: ((_ indexPath: IndexPath) -> IndexPath?)? fileprivate var didSelectRowAt: ((_ indexPath: IndexPath) -> Void)? fileprivate var didDeselectRowAt: ((_ indexPath: IndexPath) -> Void)? - fileprivate var editingStyleForRowAt: ((_ indexPath: IndexPath) -> UITableViewCellEditingStyle)? + fileprivate var editingStyleForRowAt: ((_ indexPath: IndexPath) -> UITableViewCell.EditingStyle)? fileprivate var titleForDeleteConfirmationButtonForRowAt: ((_ indexPath: IndexPath) -> String?)? fileprivate var editActionsForRowAt: ((_ indexPath: IndexPath) -> [UITableViewRowAction]?)? fileprivate var shouldIndentWhileEditingRowAt: ((_ indexPath: IndexPath) -> Bool)? @@ -290,7 +290,7 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat fileprivate var canMoveRowAt: ((_ indexPath: IndexPath) -> Bool)? fileprivate var sectionIndexTitles: (() -> [String]?)? fileprivate var sectionForSectionIndexTitle: ((_ title: String, _ index: Int) -> Int)? - fileprivate var commit: ((_ editingStyle: UITableViewCellEditingStyle, _ indexPath: IndexPath) -> Void)? + fileprivate var commit: ((_ editingStyle: UITableViewCell.EditingStyle, _ indexPath: IndexPath) -> Void)? fileprivate var moveRowAt: ((_ sourceIndexPath: IndexPath, _ destinationIndexPath: IndexPath) -> Void)? private var _leadingSwipeActionsConfigurationForRowAt: Any? @available(iOS 11, *) @@ -478,7 +478,7 @@ extension TableViewDelegate { } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - return estimatedHeightForRowAt?(indexPath) ?? UITableViewAutomaticDimension + return estimatedHeightForRowAt?(indexPath) ?? UITableView.automaticDimension } func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { @@ -529,7 +529,7 @@ extension TableViewDelegate { didDeselectRowAt?(indexPath) } - func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { return editingStyleForRowAt?(indexPath) ?? .delete } @@ -624,7 +624,7 @@ extension TableViewDelegate { return sectionForSectionIndexTitle?(title, index) ?? 0 } - func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { commit?(editingStyle, indexPath) } @@ -922,7 +922,7 @@ extension UITableView { * returns: itself so you can daisy chain the other delegate calls */ @discardableResult - public func editingStyleForRowAt(handler: @escaping (_ indexPath: IndexPath) -> UITableViewCellEditingStyle) -> Self { + public func editingStyleForRowAt(handler: @escaping (_ indexPath: IndexPath) -> UITableViewCell.EditingStyle) -> Self { return update { $0.editingStyleForRowAt = handler } } @@ -1210,7 +1210,7 @@ extension UITableView { * returns: itself so you can daisy chain the other datasource calls */ @discardableResult - public func commit(handler: @escaping (_ editingStyle: UITableViewCellEditingStyle, _ indexPath: IndexPath) -> Void) -> Self { + public func commit(handler: @escaping (_ editingStyle: UITableViewCell.EditingStyle, _ indexPath: IndexPath) -> Void) -> Self { return update { $0.commit = handler } } diff --git a/Xcode/ClosuresTests/UIControlTests.swift b/Xcode/ClosuresTests/UIControlTests.swift index 47ad6e2..3db30e0 100644 --- a/Xcode/ClosuresTests/UIControlTests.swift +++ b/Xcode/ClosuresTests/UIControlTests.swift @@ -118,21 +118,4 @@ class UIControlTests: XCTestCase { waitForExpectations(timeout: 0.2) } - - func testDelegateCleanup() { - weak var textField1: UITextField? - let textField2 = UITextField() - let textField3 = UITextField() - - textField2.didBeginEditing {} - XCTAssertEqual(textFieldDelegates.count, 1) - autoreleasepool { - textField1 = UITextField() - textField1?.didBeginEditing {} - XCTAssertEqual(textFieldDelegates.count, 2) - } - XCTAssertEqual(textFieldDelegates.count, 2) - textField3.didBeginEditing {} - XCTAssertEqual(textFieldDelegates.count, 2) - } }