diff --git a/Closures.podspec.json b/Closures.podspec.json index 445ab10..9f959cc 100644 --- a/Closures.podspec.json +++ b/Closures.podspec.json @@ -18,5 +18,6 @@ }, "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." -} \ No newline at end of file + "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": "5.0" +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..e1a1744 --- /dev/null +++ b/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. +import PackageDescription + +let package = Package( + name: "Closures", + products: [ + .library(name: "Closures", targets: ["Closures"]) + ], + dependencies: [], + targets: [ + .target(name: "Closures", path: "Xcode/Closures") + ] +) diff --git a/README.md b/README.md index 35eb425..e37242c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Whether you're a functional purist, dislike a particular API, or simply just want to organize your code a little bit, you might enjoy using this library. > ***note***
-> `Closures` currently only supports projects written in **Swift 4.0**+. +> `Closures` currently only supports projects written in **Swift 5.0**+. *** ## [Usage Overview](#usage-overview) diff --git a/Xcode/Closures.xcodeproj/project.pbxproj b/Xcode/Closures.xcodeproj/project.pbxproj index a6eccd1..f173d25 100644 --- a/Xcode/Closures.xcodeproj/project.pbxproj +++ b/Xcode/Closures.xcodeproj/project.pbxproj @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1100; ORGANIZATIONNAME = "Your Mom"; TargetAttributes = { 3F7620DD1D849B5000E17BF5 = { @@ -426,7 +426,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -449,7 +449,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/Xcode/Closures.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Xcode/Closures.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Xcode/Closures.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Xcode/Closures.xcodeproj/xcshareddata/xcschemes/Closures.xcscheme b/Xcode/Closures.xcodeproj/xcshareddata/xcschemes/Closures.xcscheme index 6a00b26..d4c233a 100644 --- a/Xcode/Closures.xcodeproj/xcshareddata/xcschemes/Closures.xcscheme +++ b/Xcode/Closures.xcodeproj/xcshareddata/xcschemes/Closures.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> + + + + @@ -40,17 +49,6 @@ - - - - - - - - : NSObject { weak var delegator: Delegator? let delegate: Delegate @@ -75,6 +78,7 @@ class DelegateWrapper: } } + @available(iOS 9.0, *) public static func update(_ delegator: Delegator, delegate: @autoclosure () -> Delegate, delegates: inout Set>, diff --git a/Xcode/Closures/Source/UICollectionView.swift b/Xcode/Closures/Source/UICollectionView.swift index a032b48..2b3e7e5 100644 --- a/Xcode/Closures/Source/UICollectionView.swift +++ b/Xcode/Closures/Source/UICollectionView.swift @@ -23,6 +23,7 @@ import UIKit /// :nodoc: private let jzyBug = 0 // Prevent the license header from showing up in Jazzy Docs for UICollectionView +@available(iOS 9.0, *) extension UICollectionView { // MARK: Common Array Usage /** @@ -110,6 +111,7 @@ extension UICollectionView { } } +@available(iOS 9.0, *) class CollectionViewDelegate: ScrollViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { fileprivate static var delegates = Set>() @@ -355,6 +357,7 @@ class CollectionViewDelegate: ScrollViewDelegate, UICollectionViewDelegateFlowLa } } +@available(iOS 9.0, *) extension UICollectionView { // MARK: Delegate and DataSource Overrides /** @@ -755,6 +758,7 @@ extension UICollectionView { } } +@available(iOS 9.0, *) extension UICollectionView { @discardableResult @objc override func update(handler: (_ delegate: CollectionViewDelegate) -> Void) -> Self { diff --git a/Xcode/Closures/Source/UIControl.swift b/Xcode/Closures/Source/UIControl.swift index 50a6b92..0f44628 100644 --- a/Xcode/Closures/Source/UIControl.swift +++ b/Xcode/Closures/Source/UIControl.swift @@ -20,6 +20,7 @@ import UIKit +@available(iOS 9.0, *) fileprivate extension UIControl { func _onChange( callerHandler: @escaping (_ value: ValueType) -> (Void), @@ -33,6 +34,7 @@ fileprivate extension UIControl { } } +@available(iOS 9.0, *) extension UIControl { public typealias EventHandler = (_ sender: UIControl, _ forEvent: UIEvent?) -> Void /** @@ -166,6 +168,7 @@ extension UIControl { } } +@available(iOS 9.0, *) extension UIControl { /** Provides the proper internal selector to call for the type of UIControlEvent @@ -223,6 +226,7 @@ extension UIControl { } } +@available(iOS 9.0, *) extension UIButton { // MARK: Common Events /** @@ -251,6 +255,7 @@ extension UIButton { } } +@available(iOS 9.0, *) extension UITextField { // MARK: Common Events /** @@ -337,6 +342,7 @@ extension UITextField { } } +@available(iOS 9.0, *) extension UITextField { // MARK: Delegate Overrides /** @@ -457,6 +463,7 @@ extension UITextField { } } +@available(iOS 9.0, *) extension UITextField: DelegatorProtocol { @discardableResult fileprivate func update(handler: (_ delegate: TextFieldDelegate) -> Void) -> Self { @@ -488,11 +495,13 @@ extension UITextField: DelegatorProtocol { } #if DEBUG +@available(iOS 9.0, *) var textFieldDelegates: Set { return TextFieldDelegate.delegates } #endif +@available(iOS 9.0, *) fileprivate final class TextFieldDelegate: NSObject, UITextFieldDelegate, DelegateProtocol { fileprivate static var delegates = Set>() @@ -557,6 +566,7 @@ fileprivate final class TextFieldDelegate: NSObject, UITextFieldDelegate, Delega } } +@available(iOS 9.0, *) extension UISwitch { // MARK: Common Events /** @@ -576,6 +586,7 @@ extension UISwitch { } } +@available(iOS 9.0, *) extension UISlider { // MARK: Common Events /** @@ -595,6 +606,7 @@ extension UISlider { } } +@available(iOS 9.0, *) extension UISegmentedControl { // MARK: Common Events /** @@ -614,6 +626,7 @@ extension UISegmentedControl { } } +@available(iOS 9.0, *) extension UIStepper { // MARK: Common Events /** @@ -633,6 +646,7 @@ extension UIStepper { } } +@available(iOS 9.0, *) extension UIPageControl { // MARK: Common Events /** @@ -652,6 +666,7 @@ extension UIPageControl { } } +@available(iOS 9.0, *) extension UIDatePicker { // MARK: Common Events /** diff --git a/Xcode/Closures/Source/UIGestureRecognizer.swift b/Xcode/Closures/Source/UIGestureRecognizer.swift index 75705bb..431a3d5 100644 --- a/Xcode/Closures/Source/UIGestureRecognizer.swift +++ b/Xcode/Closures/Source/UIGestureRecognizer.swift @@ -343,6 +343,7 @@ extension UIView { } } +@available(iOS 9.0, *) fileprivate final class GestureRecognizerDelegate: NSObject, UIGestureRecognizerDelegate, DelegateProtocol { static var delegates = Set>() @@ -396,6 +397,7 @@ fileprivate final class GestureRecognizerDelegate: NSObject, UIGestureRecognizer } } +@available(iOS 9.0, *) extension UIGestureRecognizer { // MARK: Delegate Overrides /** @@ -471,6 +473,7 @@ extension UIGestureRecognizer { } } +@available(iOS 9.0, *) extension UIGestureRecognizer: DelegatorProtocol { @discardableResult fileprivate func update(handler: (_ delegate: GestureRecognizerDelegate) -> Void) -> Self { diff --git a/Xcode/Closures/Source/UIImagePickerController.swift b/Xcode/Closures/Source/UIImagePickerController.swift index e1e145b..af14a5b 100644 --- a/Xcode/Closures/Source/UIImagePickerController.swift +++ b/Xcode/Closures/Source/UIImagePickerController.swift @@ -22,6 +22,7 @@ import UIKit import MobileCoreServices import PhotosUI +@available(iOS 9.0, *) fileprivate final class ImagePickerControllerDelegate: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, DelegateProtocol { static var delegates = Set>() @@ -49,6 +50,7 @@ fileprivate final class ImagePickerControllerDelegate: NSObject, UIImagePickerCo } } +@available(iOS 9.0, *) extension UIImagePickerController { // MARK: Convenient Presenting /** @@ -169,6 +171,7 @@ extension UIImagePickerController { } } +@available(iOS 9.0, *) extension UIImagePickerController { // MARK: Delegate Overrides /** @@ -196,6 +199,7 @@ extension UIImagePickerController { } } +@available(iOS 9.0, *) extension UIImagePickerController { // MARK: Helper Types /** @@ -317,6 +321,7 @@ extension UIImagePickerController { } } +@available(iOS 9.0, *) extension UIImagePickerController.MediaFilter: ExpressibleByIntegerLiteral { /// :nodoc: public init(integerLiteral value: Int) { @@ -324,6 +329,7 @@ extension UIImagePickerController.MediaFilter: ExpressibleByIntegerLiteral { } } +@available(iOS 9.0, *) fileprivate extension CFString { var mediaFilter: UIImagePickerController.MediaFilter { switch self { @@ -337,6 +343,7 @@ fileprivate extension CFString { } } +@available(iOS 9.0, *) extension UIImagePickerController: DelegatorProtocol { @discardableResult fileprivate func update(handler: (_ delegate: ImagePickerControllerDelegate) -> Void) -> Self { diff --git a/Xcode/Closures/Source/UIPickerView.swift b/Xcode/Closures/Source/UIPickerView.swift index 878c2be..7aa16b4 100644 --- a/Xcode/Closures/Source/UIPickerView.swift +++ b/Xcode/Closures/Source/UIPickerView.swift @@ -20,6 +20,7 @@ import UIKit +@available(iOS 9.0, *) fileprivate final class PickerViewDelegate: NSObject, UIPickerViewDelegate, UIPickerViewDataSource, DelegateProtocol { static var delegates = Set>() @@ -87,6 +88,7 @@ fileprivate final class PickerViewDelegate: NSObject, UIPickerViewDelegate, UIPi } } +@available(iOS 9.0, *) extension UIPickerView { // MARK: Common Array Usage /** @@ -422,6 +424,7 @@ extension UIPickerView { } } +@available(iOS 9.0, *) extension UIPickerView { // MARK: Delegate and DataSource Overrides /** @@ -521,6 +524,7 @@ extension UIPickerView { } } +@available(iOS 9.0, *) extension UIPickerView: DelegatorProtocol { @discardableResult fileprivate func update(handler: (_ delegate: PickerViewDelegate) -> Void) -> Self { diff --git a/Xcode/Closures/Source/UIScrollView.swift b/Xcode/Closures/Source/UIScrollView.swift index b8a3ad1..3e250ce 100644 --- a/Xcode/Closures/Source/UIScrollView.swift +++ b/Xcode/Closures/Source/UIScrollView.swift @@ -20,6 +20,7 @@ import UIKit +@available(iOS 9.0, *) class ScrollViewDelegate: NSObject, UIScrollViewDelegate, DelegateProtocol { fileprivate static var delegates = Set>() @@ -129,6 +130,7 @@ class ScrollViewDelegate: NSObject, UIScrollViewDelegate, DelegateProtocol { } } +@available(iOS 9.0, *) extension UIScrollView { // MARK: Delegate Overrides /** @@ -300,6 +302,7 @@ extension UIScrollView { } } +@available(iOS 9.0, *) extension UIScrollView: DelegatorProtocol { @discardableResult @objc func update(handler: (_ delegate: ScrollViewDelegate) -> Void) -> Self { diff --git a/Xcode/Closures/Source/UITableView.swift b/Xcode/Closures/Source/UITableView.swift index 058eca6..9dd0161 100644 --- a/Xcode/Closures/Source/UITableView.swift +++ b/Xcode/Closures/Source/UITableView.swift @@ -23,6 +23,7 @@ import UIKit /// :nodoc: private let jzyBug = 0 // Prevent the license header from showing up in Jazzy Docs for UITableView +@available(iOS 9.0, *) extension UITableView { // MARK: Common Array Usage /** @@ -241,6 +242,7 @@ extension UITableView { } } +@available(iOS 9.0, *) class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDataSource { fileprivate static var delegates = Set>() @@ -268,14 +270,18 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat fileprivate var didDeselectRowAt: ((_ indexPath: IndexPath) -> Void)? fileprivate var editingStyleForRowAt: ((_ indexPath: IndexPath) -> UITableViewCell.EditingStyle)? fileprivate var titleForDeleteConfirmationButtonForRowAt: ((_ indexPath: IndexPath) -> String?)? + @available(iOS, deprecated: 13.0) fileprivate var editActionsForRowAt: ((_ indexPath: IndexPath) -> [UITableViewRowAction]?)? fileprivate var shouldIndentWhileEditingRowAt: ((_ indexPath: IndexPath) -> Bool)? fileprivate var willBeginEditingRowAt: ((_ indexPath: IndexPath) -> Void)? fileprivate var didEndEditingRowAt: ((_ indexPath: IndexPath?) -> Void)? fileprivate var targetIndexPathForMoveFromRowAt: ((_ sourceIndexPath: IndexPath, _ proposedDestinationIndexPath: IndexPath) -> IndexPath)? fileprivate var indentationLevelForRowAt: ((_ indexPath: IndexPath) -> Int)? + @available(iOS, deprecated: 13.0) fileprivate var shouldShowMenuForRowAt: ((_ indexPath: IndexPath) -> Bool)? + @available(iOS, deprecated: 13.0) fileprivate var canPerformAction: ((_ action: Selector, _ indexPath: IndexPath, _ sender: Any?) -> Bool)? + @available(iOS, deprecated: 13.0) fileprivate var performAction: ((_ action: Selector, _ indexPath: IndexPath, _ sender: Any?) -> Void)? fileprivate var canFocusRowAt: ((_ indexPath: IndexPath) -> Bool)? fileprivate var shouldUpdateFocus: ((_ context: UITableViewFocusUpdateContext) -> Bool)? @@ -322,6 +328,38 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat _shouldSpringLoadRowAt = newValue } } + private var _shouldBeginMultipleSelectionInteractionAt: Any? + @available(iOS 13.0, *) + fileprivate var shouldBeginMultipleSelectionInteractionAt: ((_ indexPath: IndexPath) -> Bool)? { + get { + return _shouldBeginMultipleSelectionInteractionAt as? (_ indexPath: IndexPath) -> Bool + } + set { + _shouldBeginMultipleSelectionInteractionAt = newValue + } + } + + private var _didBeginMultipleSelectionInteractionAt: Any? + @available(iOS 13.0, *) + fileprivate var didBeginMultipleSelectionInteractionAt: ((_ indexPath: IndexPath) -> Void)? { + get { + return _didBeginMultipleSelectionInteractionAt as? (_ indexPath: IndexPath) -> Void + } + set { + _didBeginMultipleSelectionInteractionAt = newValue + } + } + + private var _didEndMultipleSelectionInteraction: Any? + @available(iOS 13.0, *) + fileprivate var didEndMultipleSelectionInteraction: (() -> Void)? { + get { + return _didEndMultipleSelectionInteraction as? () -> Void + } + set { + _didEndMultipleSelectionInteraction = newValue + } + } override func responds(to aSelector: Selector!) -> Bool { if #available(iOS 11, *) { @@ -336,6 +374,33 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat break } } + + if #available(iOS 13, *) { + switch aSelector { + case #selector(TableViewDelegate.tableView(_:shouldBeginMultipleSelectionInteractionAt:)): + return _shouldBeginMultipleSelectionInteractionAt != nil + case #selector(TableViewDelegate.tableView(_:didBeginMultipleSelectionInteractionAt:)): + return _didBeginMultipleSelectionInteractionAt != nil + case #selector(TableViewDelegate.tableView(_:didEndEditingRowAt:)): + return _didEndMultipleSelectionInteraction != nil + default: + break + } + } else { + switch aSelector { + case #selector(TableViewDelegate.tableView(_:editActionsForRowAt:)): + return editActionsForRowAt != nil + case #selector(TableViewDelegate.tableView(_:shouldShowMenuForRowAt:)): + return shouldShowMenuForRowAt != nil + case #selector(TableViewDelegate.tableView(_:canPerformAction:forRowAt:withSender:)): + return canPerformAction != nil + case #selector(TableViewDelegate.tableView(_:performAction:forRowAt:withSender:)): + return performAction != nil + + default: + break + } + } switch aSelector { case #selector(TableViewDelegate.tableView(_:willDisplay:forRowAt:)): @@ -386,8 +451,6 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat return editingStyleForRowAt != nil case #selector(TableViewDelegate.tableView(_:titleForDeleteConfirmationButtonForRowAt:)): return titleForDeleteConfirmationButtonForRowAt != nil - case #selector(TableViewDelegate.tableView(_:editActionsForRowAt:)): - return editActionsForRowAt != nil case #selector(TableViewDelegate.tableView(_:shouldIndentWhileEditingRowAt:)): return shouldIndentWhileEditingRowAt != nil case #selector(TableViewDelegate.tableView(_:willBeginEditingRowAt:)): @@ -398,12 +461,6 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat return targetIndexPathForMoveFromRowAt != nil case #selector(TableViewDelegate.tableView(_:indentationLevelForRowAt:)): return indentationLevelForRowAt != nil - case #selector(TableViewDelegate.tableView(_:shouldShowMenuForRowAt:)): - return shouldShowMenuForRowAt != nil - case #selector(TableViewDelegate.tableView(_:canPerformAction:forRowAt:withSender:)): - return canPerformAction != nil - case #selector(TableViewDelegate.tableView(_:canPerformAction:forRowAt:withSender:)): - return performAction != nil case #selector(TableViewDelegate.tableView(_:canFocusRowAt:)): return canFocusRowAt != nil case #selector(TableViewDelegate.tableView(_:shouldUpdateFocusIn:)): @@ -440,6 +497,7 @@ class TableViewDelegate: ScrollViewDelegate, UITableViewDelegate, UITableViewDat } } +@available(iOS 9.0, *) extension TableViewDelegate { func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { willDisplay?(cell, indexPath) @@ -537,6 +595,7 @@ extension TableViewDelegate { return titleForDeleteConfirmationButtonForRowAt?(indexPath) ?? Bundle(identifier: "com.apple.UIKit")?.localizedString(forKey: "Delete", value: nil, table: nil) } + @available(iOS, deprecated: 13.0) func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { return editActionsForRowAt?(indexPath) ?? nil } @@ -561,14 +620,17 @@ extension TableViewDelegate { return indentationLevelForRowAt?(indexPath) ?? 0 } + @available(iOS, deprecated: 13.0) func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool { return shouldShowMenuForRowAt?(indexPath) ?? false } + @available(iOS, deprecated: 13.0) func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool { return canPerformAction?(action, indexPath, sender) ?? false } + @available(iOS, deprecated: 13.0) func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) { performAction?(action, indexPath, sender) } @@ -646,8 +708,24 @@ extension TableViewDelegate { func tableView(_ tableView: UITableView, shouldSpringLoadRowAt indexPath: IndexPath, with context: UISpringLoadedInteractionContext) -> Bool { return shouldSpringLoadRowAt?(indexPath, context) ?? true } + + @available(iOS 13, *) + func tableView(_ tableView: UITableView, shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool { + return shouldBeginMultipleSelectionInteractionAt?(indexPath) ?? false + } + + @available(iOS 13, *) + func tableView(_ tableView: UITableView, didBeginMultipleSelectionInteractionAt indexPath: IndexPath) { + didBeginMultipleSelectionInteractionAt?(indexPath) + } + + @available(iOS 13, *) + func tableViewDidEndMultipleSelectionInteraction(_ tableView: UITableView) { + didEndMultipleSelectionInteraction?() + } } +@available(iOS 9.0, *) extension UITableView { // MARK: Delegate and DataSource Overrides /** @@ -945,6 +1023,7 @@ extension UITableView { * returns: itself so you can daisy chain the other delegate calls */ + @available(iOS, deprecated: 13.0) @discardableResult public func editActionsForRowAt(handler: @escaping (_ indexPath: IndexPath) -> [UITableViewRowAction]?) -> Self { return update { $0.editActionsForRowAt = handler } @@ -1017,6 +1096,7 @@ extension UITableView { * returns: itself so you can daisy chain the other delegate calls */ + @available(iOS, deprecated: 13.0) @discardableResult public func shouldShowMenuForRowAt(handler: @escaping (_ indexPath: IndexPath) -> Bool) -> Self { return update { $0.shouldShowMenuForRowAt = handler } @@ -1029,6 +1109,7 @@ extension UITableView { * returns: itself so you can daisy chain the other delegate calls */ + @available(iOS, deprecated: 13.0) @discardableResult public func canPerformAction(handler: @escaping (_ action: Selector, _ indexPath: IndexPath, _ sender: Any?) -> Bool) -> Self { return update { $0.canPerformAction = handler } @@ -1041,6 +1122,7 @@ extension UITableView { * returns: itself so you can daisy chain the other delegate calls */ + @available(iOS, deprecated: 13.0) @discardableResult public func performAction(handler: @escaping (_ action: Selector, _ indexPath: IndexPath, _ sender: Any?) -> Void) -> Self { return update { $0.performAction = handler } @@ -1261,8 +1343,27 @@ extension UITableView { public func shouldSpringLoadRowAt(handler: @escaping (_ indexPath: IndexPath, _ context: UISpringLoadedInteractionContext) -> Bool) -> Self { return update { $0.shouldSpringLoadRowAt = handler } } + + + + + @available(iOS 13, *) @discardableResult + public func shouldBeginMultipleSelectionInteraction(handler: @escaping (_ indexPath: IndexPath) -> Bool) -> Self { + return update { $0.shouldBeginMultipleSelectionInteractionAt = handler } + } + + @available(iOS 13, *) @discardableResult + public func didBeginMultipleSelectionInteractionAt(handler: @escaping (_ indexPath: IndexPath) -> Void) -> Self { + return update { $0.didBeginMultipleSelectionInteractionAt = handler } + } + + @available(iOS 13, *) @discardableResult + public func didEndMultipleSelectionInteraction(handler: @escaping () -> Void) -> Self { + return update { $0.didEndMultipleSelectionInteraction = handler } + } } +@available(iOS 9.0, *) extension UITableView { @discardableResult @objc override func update(handler: (_ delegate: TableViewDelegate) -> Void) -> Self { diff --git a/Xcode/ClosuresTests/UICollectionViewTests.swift b/Xcode/ClosuresTests/UICollectionViewTests.swift index a07f087..2672185 100644 --- a/Xcode/ClosuresTests/UICollectionViewTests.swift +++ b/Xcode/ClosuresTests/UICollectionViewTests.swift @@ -170,9 +170,13 @@ class UICollectionViewTests: XCTestCase { _ = delegate.collectionView!(collectionView, shouldDeselectItemAt: iPath) delegate.collectionView!(collectionView, didSelectItemAt: iPath) delegate.collectionView!(collectionView, didDeselectItemAt: iPath) - _ = delegate.collectionView!(collectionView, shouldShowMenuForItemAt: iPath) - _ = delegate.collectionView!(collectionView, canPerformAction: #selector(UICollectionViewTests.setUp), forItemAt: iPath, withSender: nil) - delegate.collectionView!(collectionView, performAction: #selector(UICollectionViewTests.setUp), forItemAt: iPath, withSender: nil) + if #available(iOS 13, *) { + exp.expectedFulfillmentCount -= 3 + } else { + _ = delegate.collectionView!(collectionView, shouldShowMenuForItemAt: iPath) + _ = delegate.collectionView!(collectionView, canPerformAction: #selector(UICollectionViewTests.setUp), forItemAt: iPath, withSender: nil) + delegate.collectionView!(collectionView, performAction: #selector(UICollectionViewTests.setUp), forItemAt: iPath, withSender: nil) + } _ = delegate.collectionView!(collectionView, transitionLayoutForOldLayout: collectionView.collectionViewLayout, newLayout: collectionView.collectionViewLayout) _ = delegate.collectionView!(collectionView, targetContentOffsetForProposedContentOffset: .zero) _ = delegate.collectionView!(collectionView, targetIndexPathForMoveFromItemAt: iPath, toProposedIndexPath: iPath) diff --git a/Xcode/ClosuresTests/UITableViewTests.swift b/Xcode/ClosuresTests/UITableViewTests.swift index 30c7384..263893a 100644 --- a/Xcode/ClosuresTests/UITableViewTests.swift +++ b/Xcode/ClosuresTests/UITableViewTests.swift @@ -113,9 +113,13 @@ class UITableViewTests: XCTestCase { exp.fulfill() return nil } - tableView.editActionsForRowAt { _ in - exp.fulfill() - return nil + if #available(iOS 13, *) { + exp.expectedFulfillmentCount -= 1 + } else { + tableView.editActionsForRowAt { _ in + exp.fulfill() + return nil + } } tableView.shouldIndentWhileEditingRowAt { _ in exp.fulfill() @@ -135,16 +139,20 @@ class UITableViewTests: XCTestCase { exp.fulfill() return 0 } - tableView.shouldShowMenuForRowAt { _ in - exp.fulfill() - return true - } - tableView.canPerformAction {_,_,_ in - exp.fulfill() - return true - } - tableView.performAction { _,_,_ in - exp.fulfill() + if #available(iOS 13, *) { + exp.expectedFulfillmentCount -= 3 + } else { + tableView.shouldShowMenuForRowAt { _ in + exp.fulfill() + return true + } + tableView.canPerformAction {_,_,_ in + exp.fulfill() + return true + } + tableView.performAction { _,_,_ in + exp.fulfill() + } } tableView.canFocusRowAt { _ in exp.fulfill() @@ -196,6 +204,19 @@ class UITableViewTests: XCTestCase { tableView.moveRowAt { _,_ in exp.fulfill() } + if #available(iOS 13, *) { + exp.expectedFulfillmentCount += 3 + tableView.shouldBeginMultipleSelectionInteraction { (_) -> Bool in + exp.fulfill() + return false + } + tableView.didBeginMultipleSelectionInteractionAt { (_) in + exp.fulfill() + } + tableView.didEndMultipleSelectionInteraction { + exp.fulfill() + } + } XCTAssertNotNil(tableView.delegate) XCTAssertNotNil(tableView.dataSource) @@ -228,15 +249,21 @@ class UITableViewTests: XCTestCase { delegate.tableView!(tableView, didDeselectRowAt: iPath) _ = delegate.tableView!(tableView, editingStyleForRowAt: iPath) _ = delegate.tableView!(tableView, titleForDeleteConfirmationButtonForRowAt: iPath) - _ = delegate.tableView!(tableView, editActionsForRowAt: iPath) + if #available(iOS 13, *) { + } else { + _ = delegate.tableView!(tableView, editActionsForRowAt: iPath) + } _ = delegate.tableView!(tableView, shouldIndentWhileEditingRowAt: iPath) delegate.tableView!(tableView, willBeginEditingRowAt: iPath) delegate.tableView!(tableView, didEndEditingRowAt: iPath) _ = delegate.tableView!(tableView, targetIndexPathForMoveFromRowAt: iPath, toProposedIndexPath: iPath) _ = delegate.tableView!(tableView, indentationLevelForRowAt: iPath) - _ = delegate.tableView!(tableView, shouldShowMenuForRowAt: iPath) - _ = delegate.tableView!(tableView, canPerformAction: #selector(UITableViewTests.setUp), forRowAt: iPath, withSender: nil) - _ = delegate.tableView!(tableView, performAction: #selector(UITableViewTests.setUp), forRowAt: iPath, withSender: nil) + if #available(iOS 13, *) { + } else { + _ = delegate.tableView!(tableView, shouldShowMenuForRowAt: iPath) + _ = delegate.tableView!(tableView, canPerformAction: #selector(UITableViewTests.setUp), forRowAt: iPath, withSender: nil) + _ = delegate.tableView!(tableView, performAction: #selector(UITableViewTests.setUp), forRowAt: iPath, withSender: nil) + } _ = delegate.tableView!(tableView, canFocusRowAt: iPath) _ = delegate.indexPathForPreferredFocusedView!(in: tableView) _ = datasource.tableView(tableView, numberOfRowsInSection: 0) @@ -250,7 +277,12 @@ class UITableViewTests: XCTestCase { _ = datasource.tableView!(tableView, sectionForSectionIndexTitle: "", at: 0) datasource.tableView!(tableView, commit: .delete, forRowAt: iPath) datasource.tableView!(tableView, moveRowAt: iPath, to: iPath) - + if #available(iOS 13, *) { + _ = delegate.tableView!(tableView, shouldBeginMultipleSelectionInteractionAt: iPath) + delegate.tableView!(tableView, didBeginMultipleSelectionInteractionAt: iPath) + delegate.tableViewDidEndMultipleSelectionInteraction!(tableView) + } + waitForExpectations(timeout: 0.2) } @@ -271,7 +303,12 @@ class UITableViewTests: XCTestCase { } func testTableViewMethodExpectations() { - let lastKnownDelegateCount = 41 + let lastKnownDelegateCount: Int + if #available(iOS 13, *) { + lastKnownDelegateCount = 48 + } else { + lastKnownDelegateCount = 41 + } let lastKnownDataSourceCount = 11 let delegateCount = numberOfMethods(in: UITableViewDelegate.self)