From ffc7997e2ddcaecd3eb4584739047c43fb6049c7 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 21 Oct 2016 15:10:56 +1030 Subject: [PATCH 01/21] Update .swift-version for CocoaPods --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index bb576db..9f55b2c 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -2.3 +3.0 From 60bfb9bc60a6a665eb728464c3c6c0d852ff6370 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 21 Oct 2016 15:42:50 +1030 Subject: [PATCH 02/21] Run Swift 3 conversion wizard with some minor manual fixes --- Example/FazeKit.xcodeproj/project.pbxproj | 8 +- Example/FazeKit/AppDelegate.swift | 16 +- Example/FazeKit/MenuViewController.swift | 2 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 12 +- .../Tests/NSProcessInfoAdditionsTests.swift | 2 +- Example/Tests/UIViewAdditionsTests.swift | 24 +-- FazeKit/Classes/CollectionAdditions.swift | 16 +- FazeKit/Classes/NSDateAdditions.swift | 56 +++--- .../Classes/NSDateComponentAdditions.swift | 164 +++++++++--------- FazeKit/Classes/NSProcessInfoAdditions.swift | 36 ++-- FazeKit/Classes/StringAdditions.swift | 60 +++---- FazeKit/Classes/UIDeviceAdditions.swift | 2 +- FazeKit/Classes/UIResponderAdditions.swift | 2 +- FazeKit/Classes/UIScreenAdditions.swift | 4 +- 14 files changed, 202 insertions(+), 202 deletions(-) diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index e35f27d..29c7e6b 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -489,7 +489,7 @@ MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.nextfaze.FazeKit-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -504,7 +504,7 @@ MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.nextfaze.FazeKit-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -524,7 +524,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -540,7 +540,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Example/FazeKit/AppDelegate.swift b/Example/FazeKit/AppDelegate.swift index db02051..8682fd3 100644 --- a/Example/FazeKit/AppDelegate.swift +++ b/Example/FazeKit/AppDelegate.swift @@ -27,35 +27,35 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - self.window = UIWindow(frame: UIScreen.mainScreen().bounds) + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + self.window = UIWindow(frame: UIScreen.main.bounds) self.window?.rootViewController = UINavigationController(rootViewController: MenuViewController()) - self.window?.backgroundColor = UIColor.blackColor() + self.window?.backgroundColor = UIColor.black self.window?.makeKeyAndVisible() return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/Example/FazeKit/MenuViewController.swift b/Example/FazeKit/MenuViewController.swift index 01f9ffd..092ce09 100644 --- a/Example/FazeKit/MenuViewController.swift +++ b/Example/FazeKit/MenuViewController.swift @@ -28,7 +28,7 @@ class MenuViewController: UIViewController { super.viewDidLoad() self.title = "FazeKit" - self.view.backgroundColor = UIColor.whiteColor() + self.view.backgroundColor = UIColor.white } override func didReceiveMemoryWarning() { diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 1fd7607..f0f278a 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -459,7 +459,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -535,7 +535,7 @@ PRODUCT_NAME = Pods_FazeKit_Tests; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -566,7 +566,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -600,7 +600,7 @@ PRODUCT_NAME = Pods_FazeKit_Example; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -635,7 +635,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -703,7 +703,7 @@ PRODUCT_NAME = FazeKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; diff --git a/Example/Tests/NSProcessInfoAdditionsTests.swift b/Example/Tests/NSProcessInfoAdditionsTests.swift index 19009c7..f8bb533 100644 --- a/Example/Tests/NSProcessInfoAdditionsTests.swift +++ b/Example/Tests/NSProcessInfoAdditionsTests.swift @@ -34,7 +34,7 @@ class NSProcessInfoAdditionsTests: XCTestCase { } func testOperatingSystemVersion() { - let osVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2) + let osVersion = OperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2) XCTAssertTrue(osVersion == 8, "'== major' failed") XCTAssertTrue(osVersion == (8, 1), "'== (major, minor)' failed") XCTAssertTrue(osVersion == (8, 1, 2), "'== (major, minor, patch)' failed") diff --git a/Example/Tests/UIViewAdditionsTests.swift b/Example/Tests/UIViewAdditionsTests.swift index bfbe6c4..b21d4e8 100644 --- a/Example/Tests/UIViewAdditionsTests.swift +++ b/Example/Tests/UIViewAdditionsTests.swift @@ -31,7 +31,7 @@ class UIViewAdditionsTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. - view = UIView(frame: CGRectMake(0.0, 0.0, width, height)) + view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: width, height: height)) } override func tearDown() { @@ -44,7 +44,7 @@ class UIViewAdditionsTests: XCTestCase { view.x = newX XCTAssertEqual(view.origin.x, newX, "origin.x is not as expected") - XCTAssertEqual(CGRectGetMinX(view.frame), newX, "minX is not as expected") + XCTAssertEqual(view.frame.minX, newX, "minX is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -55,7 +55,7 @@ class UIViewAdditionsTests: XCTestCase { view.y = newY XCTAssertEqual(view.origin.y, newY, "origin.y is not as expected") - XCTAssertEqual(CGRectGetMinY(view.frame), newY, "minY is not as expected") + XCTAssertEqual(view.frame.minY, newY, "minY is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -66,7 +66,7 @@ class UIViewAdditionsTests: XCTestCase { view.left = newLeft XCTAssertEqual(view.left, newLeft, "left is not as expected") - XCTAssertEqual(CGRectGetMinX(view.frame), newLeft, "minX is not as expected") + XCTAssertEqual(view.frame.minX, newLeft, "minX is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -77,7 +77,7 @@ class UIViewAdditionsTests: XCTestCase { view.right = newRight XCTAssertEqual(view.right, newRight, "right is not as expected") - XCTAssertEqual(CGRectGetMaxX(view.frame), newRight, "maxX is not as expected") + XCTAssertEqual(view.frame.maxX, newRight, "maxX is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -88,7 +88,7 @@ class UIViewAdditionsTests: XCTestCase { view.top = newTop XCTAssertEqual(view.top, newTop, "top is not as expected") - XCTAssertEqual(CGRectGetMinY(view.frame), newTop, "minY is not as expected") + XCTAssertEqual(view.frame.minY, newTop, "minY is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -99,7 +99,7 @@ class UIViewAdditionsTests: XCTestCase { view.bottom = newBottom XCTAssertEqual(view.bottom, newBottom, "bottom is not as expected") - XCTAssertEqual(CGRectGetMaxY(view.frame), newBottom, "maxY is not as expected") + XCTAssertEqual(view.frame.maxY, newBottom, "maxY is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -110,7 +110,7 @@ class UIViewAdditionsTests: XCTestCase { view.centerX = newCenterX XCTAssertEqual(view.centerX, newCenterX, "centerX is not as expected") - XCTAssertEqual(CGRectGetMidX(view.frame), newCenterX, "midX is not as expected") + XCTAssertEqual(view.frame.midX, newCenterX, "midX is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -121,7 +121,7 @@ class UIViewAdditionsTests: XCTestCase { view.centerY = newCenterY XCTAssertEqual(view.centerY, newCenterY, "centerY is not as expected") - XCTAssertEqual(CGRectGetMidY(view.frame), newCenterY, "midY is not as expected") + XCTAssertEqual(view.frame.midY, newCenterY, "midY is not as expected") XCTAssertEqual(view.width, width, "width is not as expected") XCTAssertEqual(view.height, height, "height is not as expected") @@ -131,7 +131,7 @@ class UIViewAdditionsTests: XCTestCase { let newX: CGFloat = 50.0 let newY: CGFloat = 150.0 - view.origin = CGPointMake(newX, newY) + view.origin = CGPoint(x: newX, y: newY) XCTAssertEqual(view.origin.x, newX, "origin.x is not as expected") XCTAssertEqual(view.x, newX, "x is not as expected") @@ -149,7 +149,7 @@ class UIViewAdditionsTests: XCTestCase { let newWidth: CGFloat = 50.0 let newHeight: CGFloat = 100.0 - view.size = CGSizeMake(newWidth, newHeight) + view.size = CGSize(width: newWidth, height: newHeight) XCTAssertEqual(view.width, newWidth, "width is not as expected") XCTAssertEqual(view.height, newHeight, "height is not as expected") @@ -159,7 +159,7 @@ class UIViewAdditionsTests: XCTestCase { let newWidth: CGFloat = 50.0 let newHeight: CGFloat = 100.0 - view.size = CGSizeMake(newWidth, newHeight) + view.size = CGSize(width: newWidth, height: newHeight) XCTAssertEqual(view.aspect, newWidth/newHeight, "aspect is not as expected") } diff --git a/FazeKit/Classes/CollectionAdditions.swift b/FazeKit/Classes/CollectionAdditions.swift index 6f9c7a5..68f713f 100644 --- a/FazeKit/Classes/CollectionAdditions.swift +++ b/FazeKit/Classes/CollectionAdditions.swift @@ -19,22 +19,22 @@ // Created by swoolcock on 12/08/2016. // -public extension CollectionType { - public var last: Self.Generator.Element? { - return self[self.endIndex.advancedBy(-1)] +public extension Collection { + public var last: Self.Iterator.Element? { + return self[self.index(self.endIndex, offsetBy: -1)] } - public func firstMatch(@noescape predicate: (Generator.Element) throws -> Bool) rethrows -> Generator.Element? { - guard let idx = try self.indexOf(predicate) else { return nil } + public func firstMatch(predicate: (Iterator.Element) throws -> Bool) rethrows -> Iterator.Element? { + guard let idx = try self.index(where: predicate) else { return nil } return self[idx] } } // Borrowed from: http://stackoverflow.com/a/31220067 -public extension SequenceType { +public extension Sequence { /// Categorises elements of self into a dictionary, with the keys given by keyFunc - public func categorise(@noescape keyFunc: Generator.Element -> U) -> [U: [Generator.Element]] { - var dict: [U:[Generator.Element]] = [:] + public func categorise(_ keyFunc: (Iterator.Element) -> U) -> [U: [Iterator.Element]] { + var dict: [U:[Iterator.Element]] = [:] for el in self { let key = keyFunc(el) if case nil = dict[key]?.append(el) { dict[key] = [el] } diff --git a/FazeKit/Classes/NSDateAdditions.swift b/FazeKit/Classes/NSDateAdditions.swift index 739ca08..740e210 100644 --- a/FazeKit/Classes/NSDateAdditions.swift +++ b/FazeKit/Classes/NSDateAdditions.swift @@ -21,22 +21,22 @@ import Foundation -public extension NSDate { - public func timeComponents(includeSeconds includeSeconds: Bool = false) -> NSDateComponents { - var units: NSCalendarUnit = [NSCalendarUnit.Hour, NSCalendarUnit.Minute] +public extension Date { + public func timeComponents(includeSeconds: Bool = false) -> DateComponents { + var units: NSCalendar.Unit = [NSCalendar.Unit.hour, NSCalendar.Unit.minute] if includeSeconds { - units = [NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second] + units = [NSCalendar.Unit.hour, NSCalendar.Unit.minute, NSCalendar.Unit.second] } - return NSCalendar.currentCalendar().components(units, fromDate: self) + return (Calendar.current as NSCalendar).components(units, from: self) } - public func dateComponents() -> NSDateComponents { - let units: NSCalendarUnit = [.Year, .Month, .Day, .Weekday] - return NSCalendar.currentCalendar().components(units, fromDate: self) + public func dateComponents() -> DateComponents { + let units: NSCalendar.Unit = [.year, .month, .day, .weekday] + return (Calendar.current as NSCalendar).components(units, from: self) } - public static func dateFromComponents(day day: Int = 0, month: Int = 0, year: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0, nanosecond: Int = 0) -> NSDate? { - let components = NSDateComponents() + public static func dateFromComponents(day: Int = 0, month: Int = 0, year: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0, nanosecond: Int = 0) -> Date? { + var components = DateComponents() components.day = day components.month = month components.year = year @@ -44,42 +44,42 @@ public extension NSDate { components.minute = minute components.second = second components.nanosecond = nanosecond - return NSCalendar.currentCalendar().dateFromComponents(components) + return Calendar.current.date(from: components) } - public func dateWithTimeComponents(hour hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) -> NSDate? { - let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day], fromDate: self) + public func dateWithTimeComponents(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) -> Date? { + var components = (Calendar.current as NSCalendar).components([.year, .month, .day], from: self) components.hour = hour components.minute = minute components.second = second components.nanosecond = nanosecond - return NSCalendar.currentCalendar().dateFromComponents(components) + return Calendar.current.date(from: components) } - public func stringWithFormat(format: String) -> String { - let formatter = NSDateFormatter() + public func stringWithFormat(_ format: String) -> String { + let formatter = DateFormatter() formatter.dateFormat = format - formatter.locale = NSLocale.currentLocale() - return formatter.stringFromDate(self) + formatter.locale = Locale.current + return formatter.string(from: self) } } -public func >(lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.timeIntervalSinceDate(rhs) > 0 +public func >(lhs: Date, rhs: Date) -> Bool { + return lhs.timeIntervalSince(rhs) > 0 } -public func <(lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.timeIntervalSinceDate(rhs) < 0 +public func <(lhs: Date, rhs: Date) -> Bool { + return lhs.timeIntervalSince(rhs) < 0 } -public func >=(lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.timeIntervalSinceDate(rhs) >= 0 +public func >=(lhs: Date, rhs: Date) -> Bool { + return lhs.timeIntervalSince(rhs) >= 0 } -public func <=(lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.timeIntervalSinceDate(rhs) <= 0 +public func <=(lhs: Date, rhs: Date) -> Bool { + return lhs.timeIntervalSince(rhs) <= 0 } -public func ==(lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.timeIntervalSinceDate(rhs) == 0 +public func ==(lhs: Date, rhs: Date) -> Bool { + return lhs.timeIntervalSince(rhs) == 0 } diff --git a/FazeKit/Classes/NSDateComponentAdditions.swift b/FazeKit/Classes/NSDateComponentAdditions.swift index 83641e4..81a6bba 100644 --- a/FazeKit/Classes/NSDateComponentAdditions.swift +++ b/FazeKit/Classes/NSDateComponentAdditions.swift @@ -21,8 +21,8 @@ import Foundation -public extension NSDateComponents { - public convenience init(day: Int, month: Int, year: Int) { +public extension DateComponents { + public init(day: Int, month: Int, year: Int) { self.init() self.day = day self.month = month @@ -33,7 +33,7 @@ public extension NSDateComponents { self.nanosecond = 0 } - public convenience init(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { + public init(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { self.init() self.day = 0 self.month = 0 @@ -44,7 +44,7 @@ public extension NSDateComponents { self.nanosecond = nanosecond } - public convenience init(day: Int, month: Int, year: Int, hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { + public init(day: Int, month: Int, year: Int, hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { self.init() self.day = day self.month = month @@ -55,127 +55,127 @@ public extension NSDateComponents { self.nanosecond = nanosecond } - public convenience init(datePortion: NSDateComponents) { - self.init(day: datePortion.day, month: datePortion.month, year: datePortion.year) + public init(datePortion: DateComponents) { + self.init(day: datePortion.day!, month: datePortion.month!, year: datePortion.year!) } - public convenience init(timePortion: NSDateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { + public init(timePortion: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { self.init(hour: timePortion.hour, minute: timePortion.minute, second: includeSeconds ? timePortion.second : 0, nanosecond: includeNanoseconds ? timePortion.nanosecond : 0) } - public convenience init(datePortion: NSDateComponents, timePortion: NSDateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { - self.init(day: datePortion.day, month: datePortion.month, year: datePortion.year, hour: timePortion.hour, minute: timePortion.minute, second: includeSeconds ? timePortion.second : 0, nanosecond: includeNanoseconds ? timePortion.nanosecond : 0) + public init(datePortion: DateComponents, timePortion: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { + self.init(day: datePortion.day!, month: datePortion.month!, year: datePortion.year!, hour: timePortion.hour!, minute: timePortion.minute!, second: includeSeconds ? timePortion.second! : 0, nanosecond: includeNanoseconds ? timePortion.nanosecond! : 0) } - public func compareDatePortion(other: NSDateComponents) -> NSComparisonResult { - if other.year > self.year { return .OrderedAscending } - if other.year < self.year { return .OrderedDescending } - if other.month > self.month { return .OrderedAscending } - if other.month < self.month { return .OrderedDescending } - if other.day > self.day { return .OrderedAscending } - if other.day < self.day { return .OrderedDescending } - return .OrderedSame + public func compareDatePortion(_ other: DateComponents) -> ComparisonResult { + if other.year! > self.year! { return .orderedAscending } + if other.year! < self.year! { return .orderedDescending } + if other.month! > self.month! { return .orderedAscending } + if other.month! < self.month! { return .orderedDescending } + if other.day! > self.day! { return .orderedAscending } + if other.day! < self.day! { return .orderedDescending } + return .orderedSame } - public func compareTimePortion(other: NSDateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> NSComparisonResult { - if other.hour > self.hour { return .OrderedAscending } - if other.hour < self.hour { return .OrderedDescending } - if other.minute > self.minute { return .OrderedAscending } - if other.minute < self.minute { return .OrderedDescending } + public func compareTimePortion(_ other: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> ComparisonResult { + if other.hour! > self.hour! { return .orderedAscending } + if other.hour! < self.hour! { return .orderedDescending } + if other.minute! > self.minute! { return .orderedAscending } + if other.minute! < self.minute! { return .orderedDescending } if includeSeconds { - if other.second > self.second { return .OrderedAscending } - if other.second < self.second { return .OrderedDescending } + if other.second! > self.second! { return .orderedAscending } + if other.second! < self.second! { return .orderedDescending } } if includeNanoseconds { - if other.nanosecond > self.nanosecond { return .OrderedAscending } - if other.nanosecond < self.nanosecond { return .OrderedDescending } + if other.nanosecond! > self.nanosecond! { return .orderedAscending } + if other.nanosecond! < self.nanosecond! { return .orderedDescending } } - return .OrderedSame + return .orderedSame } - public func compare(other: NSDateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> NSComparisonResult { - if other.year > self.year { return .OrderedAscending } - if other.year < self.year { return .OrderedDescending } - if other.month > self.month { return .OrderedAscending } - if other.month < self.month { return .OrderedDescending } - if other.day > self.day { return .OrderedAscending } - if other.day < self.day { return .OrderedDescending } - if other.hour > self.hour { return .OrderedAscending } - if other.hour < self.hour { return .OrderedDescending } - if other.minute > self.minute { return .OrderedAscending } - if other.minute < self.minute { return .OrderedDescending } + public func compare(_ other: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> ComparisonResult { + if other.year! > self.year! { return .orderedAscending } + if other.year! < self.year! { return .orderedDescending } + if other.month! > self.month! { return .orderedAscending } + if other.month! < self.month! { return .orderedDescending } + if other.day! > self.day! { return .orderedAscending } + if other.day! < self.day! { return .orderedDescending } + if other.hour! > self.hour! { return .orderedAscending } + if other.hour! < self.hour! { return .orderedDescending } + if other.minute! > self.minute! { return .orderedAscending } + if other.minute! < self.minute! { return .orderedDescending } if includeSeconds { - if other.second > self.second { return .OrderedAscending } - if other.second < self.second { return .OrderedDescending } + if other.second! > self.second! { return .orderedAscending } + if other.second! < self.second! { return .orderedDescending } } if includeNanoseconds { - if other.nanosecond > self.nanosecond { return .OrderedAscending } - if other.nanosecond < self.nanosecond { return .OrderedDescending } + if other.nanosecond! > self.nanosecond! { return .orderedAscending } + if other.nanosecond! < self.nanosecond! { return .orderedDescending } } - return .OrderedSame + return .orderedSame } } -public func +(lhs: NSDateComponents, rhs: NSDateComponents) -> NSDateComponents { - let comp = NSDateComponents() - comp.day = lhs.day + rhs.day - comp.month = lhs.month + rhs.month - comp.year = lhs.year + rhs.year - comp.hour = lhs.hour + rhs.hour - comp.minute = lhs.minute + rhs.minute - comp.second = lhs.second + rhs.second - comp.nanosecond = lhs.nanosecond + rhs.nanosecond +public func +(lhs: DateComponents, rhs: DateComponents) -> DateComponents { + var comp = DateComponents() + comp.day = lhs.day! + rhs.day! + comp.month = lhs.month! + rhs.month! + comp.year = lhs.year! + rhs.year! + comp.hour = lhs.hour! + rhs.hour! + comp.minute = lhs.minute! + rhs.minute! + comp.second = lhs.second! + rhs.second! + comp.nanosecond = lhs.nanosecond! + rhs.nanosecond! return comp } -public func -(lhs: NSDateComponents, rhs: NSDateComponents) -> NSDateComponents { - let comp = NSDateComponents() - comp.day = lhs.day - rhs.day - comp.month = lhs.month - rhs.month - comp.year = lhs.year - rhs.year - comp.hour = lhs.hour - rhs.hour - comp.minute = lhs.minute - rhs.minute - comp.second = lhs.second - rhs.second - comp.nanosecond = lhs.nanosecond - rhs.nanosecond +public func -(lhs: DateComponents, rhs: DateComponents) -> DateComponents { + var comp = DateComponents() + comp.day = lhs.day! - rhs.day! + comp.month = lhs.month! - rhs.month! + comp.year = lhs.year! - rhs.year! + comp.hour = lhs.hour! - rhs.hour! + comp.minute = lhs.minute! - rhs.minute! + comp.second = lhs.second! - rhs.second! + comp.nanosecond = lhs.nanosecond! - rhs.nanosecond! return comp } -public func *(lhs: NSDateComponents, rhs: Double) -> NSDateComponents { - let comp = NSDateComponents() - comp.day = Int(Double(lhs.day) * rhs) - comp.month = Int(Double(lhs.month) * rhs) - comp.year = Int(Double(lhs.year) * rhs) - comp.hour = Int(Double(lhs.hour) * rhs) - comp.minute = Int(Double(lhs.minute) * rhs) - comp.second = Int(Double(lhs.second) * rhs) - comp.nanosecond = Int(Double(lhs.nanosecond) * rhs) +public func *(lhs: DateComponents, rhs: Double) -> DateComponents { + var comp = DateComponents() + comp.day = Int(Double(lhs.day!) * rhs) + comp.month = Int(Double(lhs.month!) * rhs) + comp.year = Int(Double(lhs.year!) * rhs) + comp.hour = Int(Double(lhs.hour!) * rhs) + comp.minute = Int(Double(lhs.minute!) * rhs) + comp.second = Int(Double(lhs.second!) * rhs) + comp.nanosecond = Int(Double(lhs.nanosecond!) * rhs) return comp } -public func *(lhs: Double, rhs: NSDateComponents) -> NSDateComponents { +public func *(lhs: Double, rhs: DateComponents) -> DateComponents { return rhs * lhs } -public func /(lhs: NSDateComponents, rhs: Double) -> NSDateComponents { +public func /(lhs: DateComponents, rhs: Double) -> DateComponents { return lhs * (1 / rhs) } -public func >(lhs: NSDateComponents, rhs: NSDateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .OrderedAscending +public func >(lhs: DateComponents, rhs: DateComponents) -> Bool { + return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .orderedAscending } -public func <(lhs: NSDateComponents, rhs: NSDateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .OrderedDescending +public func <(lhs: DateComponents, rhs: DateComponents) -> Bool { + return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .orderedDescending } -public func >=(lhs: NSDateComponents, rhs: NSDateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) != .OrderedDescending +public func >=(lhs: DateComponents, rhs: DateComponents) -> Bool { + return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) != .orderedDescending } -public func <=(lhs: NSDateComponents, rhs: NSDateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) != .OrderedAscending +public func <=(lhs: DateComponents, rhs: DateComponents) -> Bool { + return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) != .orderedAscending } -public func ==(lhs: NSDateComponents, rhs: NSDateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .OrderedSame +public func ==(lhs: DateComponents, rhs: DateComponents) -> Bool { + return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .orderedSame } diff --git a/FazeKit/Classes/NSProcessInfoAdditions.swift b/FazeKit/Classes/NSProcessInfoAdditions.swift index 933623b..529e53c 100644 --- a/FazeKit/Classes/NSProcessInfoAdditions.swift +++ b/FazeKit/Classes/NSProcessInfoAdditions.swift @@ -21,74 +21,74 @@ import Foundation -public func ==(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func ==(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return lhs.majorVersion == rhs.0 && lhs.minorVersion == rhs.1 && lhs.patchVersion == rhs.2 } -public func !=(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func !=(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return lhs.majorVersion != rhs.0 || lhs.minorVersion != rhs.1 || lhs.patchVersion != rhs.2 } -public func >(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func >(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return lhs.majorVersion > rhs.0 || lhs.minorVersion > rhs.1 || lhs.patchVersion > rhs.2 } -public func <(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func <(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return lhs.majorVersion < rhs.0 || lhs.minorVersion < rhs.1 || lhs.patchVersion < rhs.2 } -public func >=(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func >=(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return !(lhs < rhs) } -public func <=(lhs: NSOperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { +public func <=(lhs: OperatingSystemVersion, rhs: (Int, Int, Int)) -> Bool { return !(lhs > rhs) } -public func ==(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func ==(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return lhs.majorVersion == rhs.0 && lhs.minorVersion == rhs.1 } -public func !=(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func !=(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return lhs.majorVersion != rhs.0 || lhs.minorVersion != rhs.1 } -public func >(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func >(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return lhs.majorVersion > rhs.0 || lhs.minorVersion > rhs.1 } -public func <(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func <(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return lhs.majorVersion < rhs.0 || lhs.minorVersion < rhs.1 } -public func >=(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func >=(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return !(lhs < rhs) } -public func <=(lhs: NSOperatingSystemVersion, rhs: (Int, Int)) -> Bool { +public func <=(lhs: OperatingSystemVersion, rhs: (Int, Int)) -> Bool { return !(lhs > rhs) } -public func ==(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func ==(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return lhs.majorVersion == rhs } -public func !=(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func !=(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return lhs.majorVersion != rhs } -public func >(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func >(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return lhs.majorVersion > rhs } -public func <(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func <(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return lhs.majorVersion < rhs } -public func >=(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func >=(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return !(lhs < rhs) } -public func <=(lhs: NSOperatingSystemVersion, rhs: Int) -> Bool { +public func <=(lhs: OperatingSystemVersion, rhs: Int) -> Bool { return !(lhs > rhs) } diff --git a/FazeKit/Classes/StringAdditions.swift b/FazeKit/Classes/StringAdditions.swift index a0fd943..88252b7 100644 --- a/FazeKit/Classes/StringAdditions.swift +++ b/FazeKit/Classes/StringAdditions.swift @@ -26,27 +26,27 @@ public extension String { return self.characters.count } - public func contains(s: String) -> Bool { - return self.rangeOfString(s) != nil + public func contains(_ s: String) -> Bool { + return self.range(of: s) != nil } - public func replace(target: String, withString: String) -> String { - return self.stringByReplacingOccurrencesOfString(target, withString: withString, options: NSStringCompareOptions.LiteralSearch, range: nil) + public func replace(_ target: String, withString: String) -> String { + return self.replacingOccurrences(of: target, with: withString, options: NSString.CompareOptions.literal, range: nil) } public subscript(i: Int) -> Character { - return self[self.startIndex.advancedBy(i)] + return self[self.characters.index(self.startIndex, offsetBy: i)] } public subscript(r: Range) -> String { - let startIndex = self.startIndex.advancedBy(max(0, r.startIndex)) - let endIndex = self.startIndex.advancedBy(min(self.length, r.endIndex)) + let startIndex = self.characters.index(self.startIndex, offsetBy: max(0, r.lowerBound)) + let endIndex = self.characters.index(self.startIndex, offsetBy: min(self.length, r.upperBound)) return self[startIndex.. Range? { - let from16 = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex) - let to16 = from16.advancedBy(nsRange.length, limit: utf16.endIndex) + public func rangeFromNSRange(_ nsRange: NSRange) -> Range? { + let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex) ?? utf16.endIndex + let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex) ?? utf16.endIndex if let from = String.Index(from16, within: self), let to = String.Index(to16, within: self) { return from ..< to @@ -54,50 +54,50 @@ public extension String { return nil } - public func substring(startIndex: Int, length: Int) -> String { - let start = self.startIndex.advancedBy(startIndex) - let end = start.advancedBy(length) - return self.substringWithRange(start.. String { + let start = self.characters.index(self.startIndex, offsetBy: startIndex) + let end = self.characters.index(start, offsetBy: length) + return self.substring(with: start.. Int? { - guard let range = self.rangeOfString(target) else { return nil } - return self.startIndex.distanceTo(range.startIndex) + public func indexOf(_ target: String) -> Int? { + guard let range = self.range(of: target) else { return nil } + return self.characters.distance(from: self.startIndex, to: range.lowerBound) } - public func indexOf(target: String, startIndex: Int) -> Int? { - let startRange = self.startIndex.advancedBy(startIndex) - guard let range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: startRange.. Int? { + let startRange = self.characters.index(self.startIndex, offsetBy: startIndex) + guard let range = self.range(of: target, options: NSString.CompareOptions.literal, range: startRange.. Int? { - guard let range: Range = self.rangeOfString(target, options: .BackwardsSearch) else { return nil } - return self.startIndex.distanceTo(range.startIndex) + public func lastIndexOf(_ target: String) -> Int? { + guard let range: Range = self.range(of: target, options: .backwards) else { return nil } + return self.characters.distance(from: self.startIndex, to: range.lowerBound) } - public func isMatch(regex: String, options: NSRegularExpressionOptions) -> Bool { + public func isMatch(_ regex: String, options: NSRegularExpression.Options) -> Bool { do { let exp = try NSRegularExpression(pattern: regex, options: options) - return exp.numberOfMatchesInString(self, options: [], range: NSMakeRange(0, self.length)) > 0 + return exp.numberOfMatches(in: self, options: [], range: NSMakeRange(0, self.length)) > 0 } catch { return false } } - public func getMatches(regex: String, options: NSRegularExpressionOptions) -> [String] { + public func getMatches(_ regex: String, options: NSRegularExpression.Options) -> [String] { do { let exp = try NSRegularExpression(pattern: regex, options: options) let nsString = self as NSString - let results = exp.matchesInString(self, options: [], range: NSMakeRange(0, self.length)) - return results.map{nsString.substringWithRange($0.range)} + let results = exp.matches(in: self, options: [], range: NSMakeRange(0, self.length)) + return results.map{nsString.substring(with: $0.range)} } catch { return [] } } public func trim() -> String { - return self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) + return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } } diff --git a/FazeKit/Classes/UIDeviceAdditions.swift b/FazeKit/Classes/UIDeviceAdditions.swift index d2828a3..c954d4a 100644 --- a/FazeKit/Classes/UIDeviceAdditions.swift +++ b/FazeKit/Classes/UIDeviceAdditions.swift @@ -23,7 +23,7 @@ import UIKit public extension UIDevice { public static func isPad() -> Bool { - return UIDevice.currentDevice().userInterfaceIdiom == .Pad + return UIDevice.current.userInterfaceIdiom == .pad } public static func is3_5Inch() -> Bool { diff --git a/FazeKit/Classes/UIResponderAdditions.swift b/FazeKit/Classes/UIResponderAdditions.swift index 320e081..bef82e5 100644 --- a/FazeKit/Classes/UIResponderAdditions.swift +++ b/FazeKit/Classes/UIResponderAdditions.swift @@ -23,6 +23,6 @@ import UIKit extension UIResponder { static func resignAnyFirstResponder() { - UIApplication.sharedApplication().sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, forEvent: nil) + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } diff --git a/FazeKit/Classes/UIScreenAdditions.swift b/FazeKit/Classes/UIScreenAdditions.swift index 3653691..1c1e210 100644 --- a/FazeKit/Classes/UIScreenAdditions.swift +++ b/FazeKit/Classes/UIScreenAdditions.swift @@ -26,8 +26,8 @@ public extension UIScreen { @nonobjc public static let maxLength4Inch: CGFloat = 568.0 @nonobjc public static let maxLength4_7Inch: CGFloat = 667.0 @nonobjc public static let maxLength5_5Inch: CGFloat = 736.0 - @nonobjc public static let screenWidth: CGFloat = { UIScreen.mainScreen().bounds.size.width }() - @nonobjc public static let screenHeight: CGFloat = { UIScreen.mainScreen().bounds.size.height }() + @nonobjc public static let screenWidth: CGFloat = { UIScreen.main.bounds.size.width }() + @nonobjc public static let screenHeight: CGFloat = { UIScreen.main.bounds.size.height }() @nonobjc public static let screenMaxLength: CGFloat = { max(screenWidth, screenHeight) }() @nonobjc public static let screenMinLength: CGFloat = { min(screenWidth, screenHeight) }() } From cbb8f17010f3145507b5bab78489e37e16ad4db8 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 21 Oct 2016 15:50:00 +1030 Subject: [PATCH 03/21] Foundation classes don't use NS anymore --- Example/Pods/Pods.xcodeproj/project.pbxproj | 24 +++++++++---------- ...ateAdditions.swift => DateAdditions.swift} | 2 +- ...ons.swift => DateComponentAdditions.swift} | 2 +- ...tions.swift => ProcessInfoAdditions.swift} | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) rename FazeKit/Classes/{NSDateAdditions.swift => DateAdditions.swift} (99%) rename FazeKit/Classes/{NSDateComponentAdditions.swift => DateComponentAdditions.swift} (99%) rename FazeKit/Classes/{NSProcessInfoAdditions.swift => ProcessInfoAdditions.swift} (98%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index f0f278a..d1dad93 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -16,14 +16,14 @@ 5535ED319233A70AC1C3C49280ECDEF2 /* UIResponderAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 686E2C4233899ACAFB954ADFA991F90F /* UIResponderAdditions.swift */; }; 5ABC9223246409B44AFA184E264261D2 /* Pods-FazeKit_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A1FEDE77480A01A2AC3F1BF93896358F /* Pods-FazeKit_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 64049AEA30380B2B26082F4CCDAD1947 /* StringAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EB5B784659EACA66F2D5917FBB8522 /* StringAdditions.swift */; }; - 7F072CBAE02C90475DD540B8D8ED3C09 /* NSDateAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F00FA13BBE84967D85F832192D687F9 /* NSDateAdditions.swift */; }; + 7F072CBAE02C90475DD540B8D8ED3C09 /* DateAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F00FA13BBE84967D85F832192D687F9 /* DateAdditions.swift */; }; 8B65A494FA5856769DEFAC285BF052F6 /* FazeKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 61F13988EE68C11BE7E445E95CF8BFCE /* FazeKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 97D1E5959A6A6AD3083101B54EC863DB /* NSDateComponentAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358A02B2D078747F51B7D08DAA894B6B /* NSDateComponentAdditions.swift */; }; + 97D1E5959A6A6AD3083101B54EC863DB /* DateComponentAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358A02B2D078747F51B7D08DAA894B6B /* DateComponentAdditions.swift */; }; A36385A1F317D62E87EE7D5A8F21E911 /* UIViewAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F79D452925B39FBBCF569A722B2F00F /* UIViewAdditions.swift */; }; BAFA5C1A9A1BCC8128A101B35FC27A0F /* Pods-FazeKit_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2601B9E18AF362D1FA9762E15669E426 /* Pods-FazeKit_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; CEFE6B1D1DD96BB2ECE4229B639DCA54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */; }; DF727BD7BA75C68423B2C104D288F7AC /* Pods-FazeKit_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F3C9BC2DA3BAC6164EE7AD012E3D24D /* Pods-FazeKit_Example-dummy.m */; }; - E699A32D308161067BC9A5861E01BF22 /* NSProcessInfoAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AC4DCD938604C35E5C7EF469BC86CB /* NSProcessInfoAdditions.swift */; }; + E699A32D308161067BC9A5861E01BF22 /* ProcessInfoAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */; }; E87975789209F1C028AAD5FF0D212735 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */; }; EEB4A634AE9CBCE1FB10D93E96D975C3 /* Pods-FazeKit_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FB4DE631D9F51D1581B54389D414895 /* Pods-FazeKit_Tests-dummy.m */; }; /* End PBXBuildFile section */ @@ -51,11 +51,11 @@ 0F0F08748B9CF253855FDB33B0ADCD94 /* UIScreenAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UIScreenAdditions.swift; sourceTree = ""; }; 153164ABC2B080D4CDA4A652F53937E5 /* CollectionAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CollectionAdditions.swift; sourceTree = ""; }; 19587F9E62528DFFB17175BFD82BBC03 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1F00FA13BBE84967D85F832192D687F9 /* NSDateAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDateAdditions.swift; sourceTree = ""; }; + 1F00FA13BBE84967D85F832192D687F9 /* DateAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateAdditions.swift; sourceTree = ""; }; 2601B9E18AF362D1FA9762E15669E426 /* Pods-FazeKit_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FazeKit_Tests-umbrella.h"; sourceTree = ""; }; 2E942A43EB3BBDA851CB6D5BD44C7D4A /* Pods-FazeKit_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FazeKit_Tests-acknowledgements.plist"; sourceTree = ""; }; 2FB4DE631D9F51D1581B54389D414895 /* Pods-FazeKit_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FazeKit_Tests-dummy.m"; sourceTree = ""; }; - 358A02B2D078747F51B7D08DAA894B6B /* NSDateComponentAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDateComponentAdditions.swift; sourceTree = ""; }; + 358A02B2D078747F51B7D08DAA894B6B /* DateComponentAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateComponentAdditions.swift; sourceTree = ""; }; 43C467D8F6ED457259EB2B5548FEFBE3 /* Pods-FazeKit_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FazeKit_Example-acknowledgements.markdown"; sourceTree = ""; }; 52C81A729DAA2801C0B6ACABDB5C4A89 /* FazeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FazeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 55808AB1308422B28E9108292A9F3314 /* Pods_FazeKit_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FazeKit_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -76,7 +76,7 @@ A1FEDE77480A01A2AC3F1BF93896358F /* Pods-FazeKit_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FazeKit_Example-umbrella.h"; sourceTree = ""; }; A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B6C175E93F3958F4BA9490F1A9D6C3B4 /* Pods-FazeKit_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FazeKit_Example-acknowledgements.plist"; sourceTree = ""; }; - B9AC4DCD938604C35E5C7EF469BC86CB /* NSProcessInfoAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSProcessInfoAdditions.swift; sourceTree = ""; }; + B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProcessInfoAdditions.swift; sourceTree = ""; }; CE2AD7B44607FA2CB0CD55F74EA74ECE /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D0EB5B784659EACA66F2D5917FBB8522 /* StringAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringAdditions.swift; sourceTree = ""; }; D38757DECB6D6DFF9F71A77396712127 /* FazeKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FazeKit-prefix.pch"; sourceTree = ""; }; @@ -245,9 +245,9 @@ isa = PBXGroup; children = ( 153164ABC2B080D4CDA4A652F53937E5 /* CollectionAdditions.swift */, - 1F00FA13BBE84967D85F832192D687F9 /* NSDateAdditions.swift */, - 358A02B2D078747F51B7D08DAA894B6B /* NSDateComponentAdditions.swift */, - B9AC4DCD938604C35E5C7EF469BC86CB /* NSProcessInfoAdditions.swift */, + 1F00FA13BBE84967D85F832192D687F9 /* DateAdditions.swift */, + 358A02B2D078747F51B7D08DAA894B6B /* DateComponentAdditions.swift */, + B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */, D0EB5B784659EACA66F2D5917FBB8522 /* StringAdditions.swift */, 6B526E01BA789E6BB17F87D13B34BD12 /* UIDeviceAdditions.swift */, 686E2C4233899ACAFB954ADFA991F90F /* UIResponderAdditions.swift */, @@ -394,9 +394,9 @@ files = ( 200FA64F634D3A48CC2E5BBF7FB78F06 /* CollectionAdditions.swift in Sources */, 43B02F311EC05FCD899E3B8D915F8D67 /* FazeKit-dummy.m in Sources */, - 7F072CBAE02C90475DD540B8D8ED3C09 /* NSDateAdditions.swift in Sources */, - 97D1E5959A6A6AD3083101B54EC863DB /* NSDateComponentAdditions.swift in Sources */, - E699A32D308161067BC9A5861E01BF22 /* NSProcessInfoAdditions.swift in Sources */, + 7F072CBAE02C90475DD540B8D8ED3C09 /* DateAdditions.swift in Sources */, + 97D1E5959A6A6AD3083101B54EC863DB /* DateComponentAdditions.swift in Sources */, + E699A32D308161067BC9A5861E01BF22 /* ProcessInfoAdditions.swift in Sources */, 64049AEA30380B2B26082F4CCDAD1947 /* StringAdditions.swift in Sources */, 3C34EFACBE8AC97A73A65A7A54758AD2 /* UIDeviceAdditions.swift in Sources */, 5535ED319233A70AC1C3C49280ECDEF2 /* UIResponderAdditions.swift in Sources */, diff --git a/FazeKit/Classes/NSDateAdditions.swift b/FazeKit/Classes/DateAdditions.swift similarity index 99% rename from FazeKit/Classes/NSDateAdditions.swift rename to FazeKit/Classes/DateAdditions.swift index 740e210..3598b76 100644 --- a/FazeKit/Classes/NSDateAdditions.swift +++ b/FazeKit/Classes/DateAdditions.swift @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations // under the License. // -// NSDateAdditions.swift +// DateAdditions.swift // FazeKit // // Created by swoolcock on 12/08/2016. diff --git a/FazeKit/Classes/NSDateComponentAdditions.swift b/FazeKit/Classes/DateComponentAdditions.swift similarity index 99% rename from FazeKit/Classes/NSDateComponentAdditions.swift rename to FazeKit/Classes/DateComponentAdditions.swift index 81a6bba..f1508ca 100644 --- a/FazeKit/Classes/NSDateComponentAdditions.swift +++ b/FazeKit/Classes/DateComponentAdditions.swift @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations // under the License. // -// NSDateComponentAdditions.swift +// DateComponentAdditions.swift // FazeKit // // Created by swoolcock on 12/08/2016. diff --git a/FazeKit/Classes/NSProcessInfoAdditions.swift b/FazeKit/Classes/ProcessInfoAdditions.swift similarity index 98% rename from FazeKit/Classes/NSProcessInfoAdditions.swift rename to FazeKit/Classes/ProcessInfoAdditions.swift index 529e53c..7e71664 100644 --- a/FazeKit/Classes/NSProcessInfoAdditions.swift +++ b/FazeKit/Classes/ProcessInfoAdditions.swift @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations // under the License. // -// NSProcessInfoAdditions.swift +// ProcessInfoAdditions.swift // FazeKit // // Created by swoolcock on 16/08/2016. From 06450d7f2ea5864ad1c22e05e501c1e5f5a59336 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 9 Nov 2016 08:54:30 +1030 Subject: [PATCH 04/21] Update Travis config for Xcode 8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 68cbcfe..6e1368d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ # * https://github.com/supermarin/xcpretty#usage language: objective-c # still specify this even though we are using swift - appears to tell travis which Xcode version to use -osx_image: xcode7.3 +osx_image: xcode8 #cache: cocoapods podfile: Example/Podfile before_install: From 897cd9c265ed0a1a15a8d30b4cf8dba5820404d4 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 9 Nov 2016 13:41:48 +1030 Subject: [PATCH 05/21] Port Date and DateComponents extensions to Swift 3, add unit tests --- Example/FazeKit.xcodeproj/project.pbxproj | 4 + Example/Tests/DateAdditionsTests.swift | 93 +++++++++ FazeKit/Classes/DateAdditions.swift | 33 +-- FazeKit/Classes/DateComponentAdditions.swift | 200 ++++++++++--------- 4 files changed, 216 insertions(+), 114 deletions(-) create mode 100644 Example/Tests/DateAdditionsTests.swift diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index 29c7e6b..ab90acf 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */; }; 78B6DD4BAF21BA4B263F3EF4 /* Pods_FazeKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DB0AD919FBE4556CA363D8B /* Pods_FazeKit_Tests.framework */; }; + C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */; }; C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */; }; /* End PBXBuildFile section */ @@ -43,6 +44,7 @@ 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewAdditionsTests.swift; sourceTree = ""; }; 739B56FA57C1D0E13427B629 /* Pods-FazeKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Tests/Pods-FazeKit_Tests.release.xcconfig"; sourceTree = ""; }; AE54F13DF076B827802B2E27 /* Pods-FazeKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Example/Pods-FazeKit_Example.debug.xcconfig"; sourceTree = ""; }; + C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAdditionsTests.swift; sourceTree = ""; }; C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSProcessInfoAdditionsTests.swift; sourceTree = ""; }; C5F04A4E1B4661BFB20EEE1D /* Pods_FazeKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FazeKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2A7D960882894C1CF4EB4D0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; @@ -123,6 +125,7 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( + C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */, C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */, 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */, 607FACE91AFB9204008FA782 /* Supporting Files */, @@ -371,6 +374,7 @@ files = ( C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */, 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */, + C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Tests/DateAdditionsTests.swift b/Example/Tests/DateAdditionsTests.swift new file mode 100644 index 0000000..79832b4 --- /dev/null +++ b/Example/Tests/DateAdditionsTests.swift @@ -0,0 +1,93 @@ +// +// Copyright 2016 NextFaze +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +// DateAdditionsTests.swift +// FazeKit +// +// Created by swoolcock on 09/11/2016. +// + +import Foundation +import XCTest +import FazeKit + +class DateAdditionsTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testDateFromComponents() { + guard + let date = Date.dateFromComponents(day: 1, month: 4, year: 2000, hour: 14, minute: 20, second: 12) + else { + XCTFail("dateFromComponents: returned nil") + return + } + + let dateComps = date.dateComponents() + XCTAssertEqual(dateComps.year, 2000, "dateComponents: year does not match") + XCTAssertEqual(dateComps.month, 4, "dateComponents: month does not match") + XCTAssertEqual(dateComps.day, 1, "dateComponents: day does not match") + XCTAssertNil(dateComps.hour, "dateComponents: hour is not nil") + XCTAssertNil(dateComps.minute, "dateComponents: minute is not nil") + XCTAssertNil(dateComps.second, "dateComponents: second is not nil") + + let timeCompsNoSec = date.timeComponents() + XCTAssertNil(timeCompsNoSec.year, "timeComponents: year is not nil") + XCTAssertNil(timeCompsNoSec.month, "timeComponents: month is not nil") + XCTAssertNil(timeCompsNoSec.day, "timeComponents: day is not nil") + XCTAssertEqual(timeCompsNoSec.hour, 14, "timeComponents: hour does not match") + XCTAssertEqual(timeCompsNoSec.minute, 20, "timeComponents: minute does not match") + XCTAssertNil(timeCompsNoSec.second, "timeComponents: second is not nil") + + let timeCompsWithSec = date.timeComponents(includeSeconds: true) + XCTAssertNil(timeCompsWithSec.year, "timeComponents(includeSeconds: true): year is not nil") + XCTAssertNil(timeCompsWithSec.month, "timeComponents(includeSeconds: true): month is not nil") + XCTAssertNil(timeCompsWithSec.day, "timeComponents(includeSeconds: true): day is not nil") + XCTAssertEqual(timeCompsWithSec.hour, 14, "timeComponents(includeSeconds: true): hour does not match") + XCTAssertEqual(timeCompsWithSec.minute, 20, "timeComponents(includeSeconds: true): minute does not match") + XCTAssertEqual(timeCompsWithSec.second, 12, "timeComponents(includeSeconds: true): second does not match") + } + + func testDateWithTimeComponents() { + guard + let date = Date.dateFromComponents(day: 3, month: 10, year: 2010) + else { + XCTFail("dateFromComponents: returned nil") + return + } + + guard + let dateWithTimeComponents = date.dateWithTimeComponents(hour: 12, minute: 10, second: 20) + else { + XCTFail("dateWithTimeComponents: returned nil") + return + } + + let dateComponents = dateWithTimeComponents.dateComponents() + let timeComponents = dateWithTimeComponents.timeComponents(includeSeconds: true) + XCTAssertEqual(dateComponents.year, 2010, "dateWithTimeComponents: year does not match") + XCTAssertEqual(dateComponents.month, 10, "dateWithTimeComponents: month does not match") + XCTAssertEqual(dateComponents.day, 3, "dateWithTimeComponents: day does not match") + XCTAssertEqual(timeComponents.hour, 12, "dateWithTimeComponents: hour does not match") + XCTAssertEqual(timeComponents.minute, 10, "dateWithTimeComponents: minute does not match") + XCTAssertEqual(timeComponents.second, 20, "dateWithTimeComponents: second does not match") + } +} diff --git a/FazeKit/Classes/DateAdditions.swift b/FazeKit/Classes/DateAdditions.swift index 3598b76..a0f1e7b 100644 --- a/FazeKit/Classes/DateAdditions.swift +++ b/FazeKit/Classes/DateAdditions.swift @@ -35,7 +35,13 @@ public extension Date { return (Calendar.current as NSCalendar).components(units, from: self) } - public static func dateFromComponents(day: Int = 0, month: Int = 0, year: Int = 0, hour: Int = 0, minute: Int = 0, second: Int = 0, nanosecond: Int = 0) -> Date? { + public static func dateFromComponents(day: Int? = nil, + month: Int? = nil, + year: Int? = nil, + hour: Int? = nil, + minute: Int? = nil, + second: Int? = nil, + nanosecond: Int? = nil) -> Date? { var components = DateComponents() components.day = day components.month = month @@ -47,7 +53,10 @@ public extension Date { return Calendar.current.date(from: components) } - public func dateWithTimeComponents(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) -> Date? { + public func dateWithTimeComponents(hour: Int? = 0, + minute: Int? = 0, + second: Int? = nil, + nanosecond: Int? = nil) -> Date? { var components = (Calendar.current as NSCalendar).components([.year, .month, .day], from: self) components.hour = hour components.minute = minute @@ -63,23 +72,3 @@ public extension Date { return formatter.string(from: self) } } - -public func >(lhs: Date, rhs: Date) -> Bool { - return lhs.timeIntervalSince(rhs) > 0 -} - -public func <(lhs: Date, rhs: Date) -> Bool { - return lhs.timeIntervalSince(rhs) < 0 -} - -public func >=(lhs: Date, rhs: Date) -> Bool { - return lhs.timeIntervalSince(rhs) >= 0 -} - -public func <=(lhs: Date, rhs: Date) -> Bool { - return lhs.timeIntervalSince(rhs) <= 0 -} - -public func ==(lhs: Date, rhs: Date) -> Bool { - return lhs.timeIntervalSince(rhs) == 0 -} diff --git a/FazeKit/Classes/DateComponentAdditions.swift b/FazeKit/Classes/DateComponentAdditions.swift index f1508ca..f87bda2 100644 --- a/FazeKit/Classes/DateComponentAdditions.swift +++ b/FazeKit/Classes/DateComponentAdditions.swift @@ -22,133 +22,153 @@ import Foundation public extension DateComponents { - public init(day: Int, month: Int, year: Int) { - self.init() - self.day = day - self.month = month - self.year = year - self.hour = 0 - self.minute = 0 - self.second = 0 - self.nanosecond = 0 - } - - public init(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { - self.init() - self.day = 0 - self.month = 0 - self.year = 0 - self.hour = hour - self.minute = minute - self.second = second - self.nanosecond = nanosecond - } - - public init(day: Int, month: Int, year: Int, hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0) { - self.init() - self.day = day - self.month = month - self.year = year - self.hour = hour - self.minute = minute - self.second = second - self.nanosecond = nanosecond - } - public init(datePortion: DateComponents) { - self.init(day: datePortion.day!, month: datePortion.month!, year: datePortion.year!) + self.init(year: datePortion.year, month: datePortion.month, day: datePortion.day) } public init(timePortion: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { - self.init(hour: timePortion.hour, minute: timePortion.minute, second: includeSeconds ? timePortion.second : 0, nanosecond: includeNanoseconds ? timePortion.nanosecond : 0) + self.init(hour: timePortion.hour, + minute: timePortion.minute, + second: includeSeconds ? timePortion.second : nil, + nanosecond: includeNanoseconds ? timePortion.nanosecond : nil) } public init(datePortion: DateComponents, timePortion: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) { - self.init(day: datePortion.day!, month: datePortion.month!, year: datePortion.year!, hour: timePortion.hour!, minute: timePortion.minute!, second: includeSeconds ? timePortion.second! : 0, nanosecond: includeNanoseconds ? timePortion.nanosecond! : 0) + self.init(year: datePortion.year, + month: datePortion.month, + day: datePortion.day, + hour: timePortion.hour, + minute: timePortion.minute, + second: includeSeconds ? timePortion.second : nil, + nanosecond: includeNanoseconds ? timePortion.nanosecond : nil) } - public func compareDatePortion(_ other: DateComponents) -> ComparisonResult { - if other.year! > self.year! { return .orderedAscending } - if other.year! < self.year! { return .orderedDescending } - if other.month! > self.month! { return .orderedAscending } - if other.month! < self.month! { return .orderedDescending } - if other.day! > self.day! { return .orderedAscending } - if other.day! < self.day! { return .orderedDescending } + private static func comparePairs(pairs: [(Int?, Int?)]) -> ComparisonResult { + for pair in pairs { + if pair.0 == nil && pair.1 != nil { + return .orderedAscending + } + if pair.0 != nil && pair.1 == nil { + return .orderedDescending + } + if let lhs = pair.0, let rhs = pair.1 { + if lhs > rhs { return .orderedAscending } + if lhs < rhs { return .orderedDescending } + } + } return .orderedSame } + public func compareDatePortion(_ other: DateComponents) -> ComparisonResult { + let pairs = [(other.year, self.year), + (other.month, self.month), + (other.day, self.day)] + return DateComponents.comparePairs(pairs: pairs) + } + public func compareTimePortion(_ other: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> ComparisonResult { - if other.hour! > self.hour! { return .orderedAscending } - if other.hour! < self.hour! { return .orderedDescending } - if other.minute! > self.minute! { return .orderedAscending } - if other.minute! < self.minute! { return .orderedDescending } + var pairs = [(other.hour, self.hour), + (other.minute, self.minute)] if includeSeconds { - if other.second! > self.second! { return .orderedAscending } - if other.second! < self.second! { return .orderedDescending } + pairs.append((other.second, self.second)) } if includeNanoseconds { - if other.nanosecond! > self.nanosecond! { return .orderedAscending } - if other.nanosecond! < self.nanosecond! { return .orderedDescending } + pairs.append((other.nanosecond, self.nanosecond)) } - return .orderedSame + return DateComponents.comparePairs(pairs: pairs) } public func compare(_ other: DateComponents, includeSeconds: Bool = true, includeNanoseconds: Bool = false) -> ComparisonResult { - if other.year! > self.year! { return .orderedAscending } - if other.year! < self.year! { return .orderedDescending } - if other.month! > self.month! { return .orderedAscending } - if other.month! < self.month! { return .orderedDescending } - if other.day! > self.day! { return .orderedAscending } - if other.day! < self.day! { return .orderedDescending } - if other.hour! > self.hour! { return .orderedAscending } - if other.hour! < self.hour! { return .orderedDescending } - if other.minute! > self.minute! { return .orderedAscending } - if other.minute! < self.minute! { return .orderedDescending } + var pairs = [(other.year, self.year), + (other.month, self.month), + (other.day, self.day), + (other.hour, self.hour), + (other.minute, self.minute)] if includeSeconds { - if other.second! > self.second! { return .orderedAscending } - if other.second! < self.second! { return .orderedDescending } + pairs.append((other.second, self.second)) } if includeNanoseconds { - if other.nanosecond! > self.nanosecond! { return .orderedAscending } - if other.nanosecond! < self.nanosecond! { return .orderedDescending } + pairs.append((other.nanosecond, self.nanosecond)) } - return .orderedSame + return DateComponents.comparePairs(pairs: pairs) } } public func +(lhs: DateComponents, rhs: DateComponents) -> DateComponents { var comp = DateComponents() - comp.day = lhs.day! + rhs.day! - comp.month = lhs.month! + rhs.month! - comp.year = lhs.year! + rhs.year! - comp.hour = lhs.hour! + rhs.hour! - comp.minute = lhs.minute! + rhs.minute! - comp.second = lhs.second! + rhs.second! - comp.nanosecond = lhs.nanosecond! + rhs.nanosecond! + if lhs.day != nil || rhs.day != nil { + comp.day = (lhs.day ?? 0) + (rhs.day ?? 0) + } + if lhs.month != nil || rhs.month != nil { + comp.month = (lhs.month ?? 0) + (rhs.month ?? 0) + } + if lhs.year != nil || rhs.year != nil { + comp.year = (lhs.year ?? 0) + (rhs.year ?? 0) + } + if lhs.hour != nil || rhs.hour != nil { + comp.hour = (lhs.hour ?? 0) + (rhs.hour ?? 0) + } + if lhs.minute != nil || rhs.minute != nil { + comp.minute = (lhs.minute ?? 0) + (rhs.minute ?? 0) + } + if lhs.second != nil || rhs.second != nil { + comp.second = (lhs.second ?? 0) + (rhs.second ?? 0) + } + if lhs.nanosecond != nil || rhs.nanosecond != nil { + comp.nanosecond = (lhs.nanosecond ?? 0) + (rhs.nanosecond ?? 0) + } return comp } public func -(lhs: DateComponents, rhs: DateComponents) -> DateComponents { var comp = DateComponents() - comp.day = lhs.day! - rhs.day! - comp.month = lhs.month! - rhs.month! - comp.year = lhs.year! - rhs.year! - comp.hour = lhs.hour! - rhs.hour! - comp.minute = lhs.minute! - rhs.minute! - comp.second = lhs.second! - rhs.second! - comp.nanosecond = lhs.nanosecond! - rhs.nanosecond! + if lhs.day != nil || rhs.day != nil { + comp.day = (lhs.day ?? 0) - (rhs.day ?? 0) + } + if lhs.month != nil || rhs.month != nil { + comp.month = (lhs.month ?? 0) - (rhs.month ?? 0) + } + if lhs.year != nil || rhs.year != nil { + comp.year = (lhs.year ?? 0) - (rhs.year ?? 0) + } + if lhs.hour != nil || rhs.hour != nil { + comp.hour = (lhs.hour ?? 0) - (rhs.hour ?? 0) + } + if lhs.minute != nil || rhs.minute != nil { + comp.minute = (lhs.minute ?? 0) - (rhs.minute ?? 0) + } + if lhs.second != nil || rhs.second != nil { + comp.second = (lhs.second ?? 0) - (rhs.second ?? 0) + } + if lhs.nanosecond != nil || rhs.nanosecond != nil { + comp.nanosecond = (lhs.nanosecond ?? 0) - (rhs.nanosecond ?? 0) + } return comp } public func *(lhs: DateComponents, rhs: Double) -> DateComponents { var comp = DateComponents() - comp.day = Int(Double(lhs.day!) * rhs) - comp.month = Int(Double(lhs.month!) * rhs) - comp.year = Int(Double(lhs.year!) * rhs) - comp.hour = Int(Double(lhs.hour!) * rhs) - comp.minute = Int(Double(lhs.minute!) * rhs) - comp.second = Int(Double(lhs.second!) * rhs) - comp.nanosecond = Int(Double(lhs.nanosecond!) * rhs) + if lhs.day != nil { + comp.day = Int(Double(lhs.day!) * rhs) + } + if lhs.month != nil { + comp.month = Int(Double(lhs.month!) * rhs) + } + if lhs.year != nil { + comp.year = Int(Double(lhs.year!) * rhs) + } + if lhs.hour != nil { + comp.hour = Int(Double(lhs.hour!) * rhs) + } + if lhs.minute != nil { + comp.minute = Int(Double(lhs.minute!) * rhs) + } + if lhs.second != nil { + comp.second = Int(Double(lhs.second!) * rhs) + } + if lhs.nanosecond != nil { + comp.nanosecond = Int(Double(lhs.nanosecond!) * rhs) + } return comp } @@ -175,7 +195,3 @@ public func >=(lhs: DateComponents, rhs: DateComponents) -> Bool { public func <=(lhs: DateComponents, rhs: DateComponents) -> Bool { return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) != .orderedAscending } - -public func ==(lhs: DateComponents, rhs: DateComponents) -> Bool { - return lhs.compare(rhs, includeSeconds: true, includeNanoseconds: true) == .orderedSame -} From c5c40f449606a4fbdd67d8f0c80d90b9d6c56d2c Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 9 Nov 2016 13:47:41 +1030 Subject: [PATCH 06/21] Update simulator target in Travis config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6e1368d..5781719 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ script: - set -o pipefail - xcodebuild -version - xcodebuild -showsdks -- xcodebuild build test -workspace Example/FazeKit.xcworkspace -scheme FazeKit-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty +- xcodebuild build test -workspace Example/FazeKit.xcworkspace -scheme FazeKit-Example -sdk iphonesimulator10.0 ONLY_ACTIVE_ARCH=NO | xcpretty - pod lib lint notifications: slack: From 6422854eed15b7310fefe1b86adb0db9516158d7 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 9 Nov 2016 15:43:56 +1030 Subject: [PATCH 07/21] Add unit tests for CollectionAdditions --- Example/FazeKit.xcodeproj/project.pbxproj | 4 + Example/Tests/CollectionAdditionsTests.swift | 77 ++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 Example/Tests/CollectionAdditionsTests.swift diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index ab90acf..14df81d 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */; }; 78B6DD4BAF21BA4B263F3EF4 /* Pods_FazeKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DB0AD919FBE4556CA363D8B /* Pods_FazeKit_Tests.framework */; }; C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */; }; + C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */; }; C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */; }; /* End PBXBuildFile section */ @@ -45,6 +46,7 @@ 739B56FA57C1D0E13427B629 /* Pods-FazeKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Tests/Pods-FazeKit_Tests.release.xcconfig"; sourceTree = ""; }; AE54F13DF076B827802B2E27 /* Pods-FazeKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Example/Pods-FazeKit_Example.debug.xcconfig"; sourceTree = ""; }; C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAdditionsTests.swift; sourceTree = ""; }; + C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdditionsTests.swift; sourceTree = ""; }; C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSProcessInfoAdditionsTests.swift; sourceTree = ""; }; C5F04A4E1B4661BFB20EEE1D /* Pods_FazeKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FazeKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2A7D960882894C1CF4EB4D0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; @@ -125,6 +127,7 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( + C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */, C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */, C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */, 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */, @@ -375,6 +378,7 @@ C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */, 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */, C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */, + C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Tests/CollectionAdditionsTests.swift b/Example/Tests/CollectionAdditionsTests.swift new file mode 100644 index 0000000..311f2ae --- /dev/null +++ b/Example/Tests/CollectionAdditionsTests.swift @@ -0,0 +1,77 @@ +// +// Copyright 2016 NextFaze +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +// CollectionAdditionsTests.swift +// FazeKit +// +// Created by swoolcock on 09/11/2016. +// + +import Foundation +import XCTest +import FazeKit + +class CollectionAdditionsTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testCollectionLast() { + let intArray = [3, 1, 4, 1, 5] + XCTAssertEqual(intArray.last, 5, "Collection.last: last element did not match") + } + + func testCollectionFirstMatch() { + let stringArray = ["hello", "world", "this", "is", "a", "unit", "test"] + XCTAssertEqual(stringArray.firstMatch { $0[0] == "t" }, "this", "Collection.firstMatch: couldn't find element") + XCTAssertNil(stringArray.firstMatch { $0[0] == "z" }, "Collection.firstMatch: found something we shouldn't") + } + + func testSequenceCategorise() { + struct CategoriseTestStruct { + var name: String + var age: Int + } + + var categoriseArray: [CategoriseTestStruct] = [] + categoriseArray.append(CategoriseTestStruct(name: "John", age: 32)) + categoriseArray.append(CategoriseTestStruct(name: "Peter", age: 12)) + categoriseArray.append(CategoriseTestStruct(name: "Michael", age: 30)) + categoriseArray.append(CategoriseTestStruct(name: "Philip", age: 22)) + categoriseArray.append(CategoriseTestStruct(name: "Lucy", age: 53)) + categoriseArray.append(CategoriseTestStruct(name: "Anna", age: 25)) + categoriseArray.append(CategoriseTestStruct(name: "Aaron", age: 40)) + + let categorised = categoriseArray.categorise { return $0.name[0] } + // result should be grouped on A, J, L, M, and P + XCTAssertEqual(categorised.count, 5, "Sequence.categorise: wrong number of categories") + XCTAssertEqual(categorised.keys.sorted(), ["A", "J", "L", "M", "P"], "Sequence.categorise: wrong categories") + XCTAssertEqual(categorised["A"]?.count, 2) + XCTAssertEqual(categorised["J"]?.count, 1) + XCTAssertEqual(categorised["L"]?.count, 1) + XCTAssertEqual(categorised["M"]?.count, 1) + XCTAssertEqual(categorised["P"]?.count, 2) + XCTAssertEqual(categorised["A"]!.flatMap({$0.name}).sorted(), ["Aaron", "Anna"]) + XCTAssertEqual(categorised["J"]!.flatMap({$0.name}), ["John"]) + XCTAssertEqual(categorised["L"]!.flatMap({$0.name}), ["Lucy"]) + XCTAssertEqual(categorised["M"]!.flatMap({$0.name}), ["Michael"]) + XCTAssertEqual(categorised["P"]!.flatMap({$0.name}).sorted(), ["Peter", "Philip"]) + } +} From 5535cd8e143da56e61b4b6145a797fc5cca1928a Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 9 Nov 2016 15:54:21 +1030 Subject: [PATCH 08/21] Add operators to dictionaries --- Example/Tests/CollectionAdditionsTests.swift | 16 ++++++++++++++ FazeKit/Classes/CollectionAdditions.swift | 23 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Example/Tests/CollectionAdditionsTests.swift b/Example/Tests/CollectionAdditionsTests.swift index 311f2ae..9da4db1 100644 --- a/Example/Tests/CollectionAdditionsTests.swift +++ b/Example/Tests/CollectionAdditionsTests.swift @@ -74,4 +74,20 @@ class CollectionAdditionsTests: XCTestCase { XCTAssertEqual(categorised["M"]!.flatMap({$0.name}), ["Michael"]) XCTAssertEqual(categorised["P"]!.flatMap({$0.name}).sorted(), ["Peter", "Philip"]) } + + func testDictionaryOperators() { + var dict1 = ["Foo": 1, "Bar": 2] + let dict2 = ["Hello": 3, "World": 4, "Foo": 5] + XCTAssertEqual(dict1 + dict2, ["Foo": 5, "Bar": 2, "Hello": 3, "World": 4], "Dictionary + operator failed") + + dict1 += ["Bar": 6, "Test": 7] + XCTAssertEqual(dict1, ["Foo": 1, "Bar": 6, "Test": 7], "Dictionary += operator failed") + + var dict3 = ["Foo": 1, "Bar": 2] + let dict4 = ["Bar": 3, "Test": 5] + XCTAssertEqual(dict3 - dict4, ["Foo": 1], "Dictionary - operator failed") + + dict3 -= ["Bar": 3, "Test": 5, "Hello": 10] + XCTAssertEqual(dict3, ["Foo": 1], "Dictionary -= operator failed") + } } diff --git a/FazeKit/Classes/CollectionAdditions.swift b/FazeKit/Classes/CollectionAdditions.swift index 68f713f..d4d4518 100644 --- a/FazeKit/Classes/CollectionAdditions.swift +++ b/FazeKit/Classes/CollectionAdditions.swift @@ -42,3 +42,26 @@ public extension Sequence { return dict } } + +public func +(lhs: Dictionary, rhs: Dictionary) -> Dictionary { + var dict = Dictionary() + lhs.forEach { dict[$0.key] = $0.value } + rhs.forEach { dict[$0.key] = $0.value } + return dict +} + +public func -(lhs: Dictionary, rhs: Dictionary) -> Dictionary { + var dict = Dictionary() + lhs.forEach { dict[$0.key] = $0.value } + rhs.forEach { dict.removeValue(forKey: $0.key) } + return dict +} + +public func +=(lhs: inout Dictionary, rhs: Dictionary) { + rhs.forEach { lhs[$0.key] = $0.value } +} + +public func -=(lhs: inout Dictionary, rhs: Dictionary) { + rhs.forEach { lhs.removeValue(forKey: $0.key) } +} + From 4645e30f37c1fbdbf4b0d524f7861750ec20396d Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 10 Nov 2016 08:36:40 +1030 Subject: [PATCH 09/21] Rename NSProcessInfoAdditionsTests in line with Swift 3 --- Example/FazeKit.xcodeproj/project.pbxproj | 8 ++++---- ...ditionsTests.swift => ProcessInfoAdditionsTests.swift} | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename Example/Tests/{NSProcessInfoAdditionsTests.swift => ProcessInfoAdditionsTests.swift} (96%) diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index 14df81d..30e2bb4 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -16,7 +16,7 @@ 78B6DD4BAF21BA4B263F3EF4 /* Pods_FazeKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DB0AD919FBE4556CA363D8B /* Pods_FazeKit_Tests.framework */; }; C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */; }; C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */; }; - C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */; }; + C2E94BAE1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -47,7 +47,7 @@ AE54F13DF076B827802B2E27 /* Pods-FazeKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Example/Pods-FazeKit_Example.debug.xcconfig"; sourceTree = ""; }; C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAdditionsTests.swift; sourceTree = ""; }; C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdditionsTests.swift; sourceTree = ""; }; - C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSProcessInfoAdditionsTests.swift; sourceTree = ""; }; + C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessInfoAdditionsTests.swift; sourceTree = ""; }; C5F04A4E1B4661BFB20EEE1D /* Pods_FazeKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FazeKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2A7D960882894C1CF4EB4D0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; FAD6E5E790BC646CAF8A952D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; @@ -129,7 +129,7 @@ children = ( C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */, C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */, - C2E94BAD1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift */, + C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */, 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */, 607FACE91AFB9204008FA782 /* Supporting Files */, ); @@ -375,7 +375,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C2E94BAE1D62CDD5007A7A4C /* NSProcessInfoAdditionsTests.swift in Sources */, + C2E94BAE1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift in Sources */, 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */, C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */, C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */, diff --git a/Example/Tests/NSProcessInfoAdditionsTests.swift b/Example/Tests/ProcessInfoAdditionsTests.swift similarity index 96% rename from Example/Tests/NSProcessInfoAdditionsTests.swift rename to Example/Tests/ProcessInfoAdditionsTests.swift index f8bb533..130e4a0 100644 --- a/Example/Tests/NSProcessInfoAdditionsTests.swift +++ b/Example/Tests/ProcessInfoAdditionsTests.swift @@ -13,7 +13,7 @@ // License for the specific language governing permissions and limitations // under the License. // -// NSProcessInfoAdditionsTests.swift +// ProcessInfoAdditionsTests.swift // FazeKit // // Created by swoolcock on 16/08/2016. @@ -23,7 +23,7 @@ import UIKit import XCTest import FazeKit -class NSProcessInfoAdditionsTests: XCTestCase { +class ProcessInfoAdditionsTests: XCTestCase { override func setUp() { super.setUp() From 93986f94a37505a333f2b2d0a87626deeb886738 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 10 Nov 2016 12:58:59 +1030 Subject: [PATCH 10/21] Force simulator version for Travis testing --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5781719..591aafc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ script: - set -o pipefail - xcodebuild -version - xcodebuild -showsdks -- xcodebuild build test -workspace Example/FazeKit.xcworkspace -scheme FazeKit-Example -sdk iphonesimulator10.0 ONLY_ACTIVE_ARCH=NO | xcpretty +- xcodebuild build test -workspace Example/FazeKit.xcworkspace -scheme FazeKit-Example -sdk iphonesimulator10.0 -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.0' ONLY_ACTIVE_ARCH=NO | xcpretty - pod lib lint notifications: slack: From 2af2c5012144e288306db83acb2ce4badaf6cf11 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 10 Nov 2016 16:15:15 +1030 Subject: [PATCH 11/21] Add Multicast class and operator overloads --- Example/Pods/Pods.xcodeproj/project.pbxproj | 4 ++ FazeKit/Classes/Multicast.swift | 76 +++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 FazeKit/Classes/Multicast.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index d1dad93..5ac90a6 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 97D1E5959A6A6AD3083101B54EC863DB /* DateComponentAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358A02B2D078747F51B7D08DAA894B6B /* DateComponentAdditions.swift */; }; A36385A1F317D62E87EE7D5A8F21E911 /* UIViewAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F79D452925B39FBBCF569A722B2F00F /* UIViewAdditions.swift */; }; BAFA5C1A9A1BCC8128A101B35FC27A0F /* Pods-FazeKit_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2601B9E18AF362D1FA9762E15669E426 /* Pods-FazeKit_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2D50E9F1DD41DC3009517F4 /* Multicast.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D50E9E1DD41DC3009517F4 /* Multicast.swift */; }; CEFE6B1D1DD96BB2ECE4229B639DCA54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */; }; DF727BD7BA75C68423B2C104D288F7AC /* Pods-FazeKit_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F3C9BC2DA3BAC6164EE7AD012E3D24D /* Pods-FazeKit_Example-dummy.m */; }; E699A32D308161067BC9A5861E01BF22 /* ProcessInfoAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */; }; @@ -77,6 +78,7 @@ A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B6C175E93F3958F4BA9490F1A9D6C3B4 /* Pods-FazeKit_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FazeKit_Example-acknowledgements.plist"; sourceTree = ""; }; B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProcessInfoAdditions.swift; sourceTree = ""; }; + C2D50E9E1DD41DC3009517F4 /* Multicast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Multicast.swift; sourceTree = ""; }; CE2AD7B44607FA2CB0CD55F74EA74ECE /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D0EB5B784659EACA66F2D5917FBB8522 /* StringAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringAdditions.swift; sourceTree = ""; }; D38757DECB6D6DFF9F71A77396712127 /* FazeKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FazeKit-prefix.pch"; sourceTree = ""; }; @@ -253,6 +255,7 @@ 686E2C4233899ACAFB954ADFA991F90F /* UIResponderAdditions.swift */, 0F0F08748B9CF253855FDB33B0ADCD94 /* UIScreenAdditions.swift */, 6F79D452925B39FBBCF569A722B2F00F /* UIViewAdditions.swift */, + C2D50E9E1DD41DC3009517F4 /* Multicast.swift */, ); path = Classes; sourceTree = ""; @@ -400,6 +403,7 @@ 64049AEA30380B2B26082F4CCDAD1947 /* StringAdditions.swift in Sources */, 3C34EFACBE8AC97A73A65A7A54758AD2 /* UIDeviceAdditions.swift in Sources */, 5535ED319233A70AC1C3C49280ECDEF2 /* UIResponderAdditions.swift in Sources */, + C2D50E9F1DD41DC3009517F4 /* Multicast.swift in Sources */, 38CE621C29F38697D6D0E3A20D086C0F /* UIScreenAdditions.swift in Sources */, A36385A1F317D62E87EE7D5A8F21E911 /* UIViewAdditions.swift in Sources */, ); diff --git a/FazeKit/Classes/Multicast.swift b/FazeKit/Classes/Multicast.swift new file mode 100644 index 0000000..156097f --- /dev/null +++ b/FazeKit/Classes/Multicast.swift @@ -0,0 +1,76 @@ +// +// Multicast.swift +// Pods +// +// Created by swoolcock on 10/11/2016. +// +// + +import Foundation + +open class Multicast { + fileprivate var blocks: [() -> ()] = [] + fileprivate var selectors: [(WeakRef, Selector)] = [] + + public init() { + } + + public func clear() { + self.blocks.removeAll() + self.selectors.removeAll() + } + + public func clearBlocks() { + self.blocks.removeAll() + } + + public func clearSelectors() { + self.selectors.removeAll() + } + + public func invoke(delaySeconds: Double? = nil) { + if let delaySeconds = delaySeconds { + DispatchQueue.main.asyncAfter(deadline: .now() + delaySeconds) { + for block in self.blocks { + block() + } + for pairs in self.selectors { + pairs.0.value?.perform(pairs.1) + } + } + } else { + for block in self.blocks { + block() + } + for pairs in self.selectors { + pairs.0.value?.perform(pairs.1) + } + } + } +} + +public func +=(lhs: inout Multicast, rhs: @escaping () -> ()) { + lhs.blocks.append(rhs) +} + +public func +=(lhs: inout Multicast, rhs: (AnyObject, Selector)) { + if !(rhs.0.responds(to: rhs.1)) { + // error: doesn't respond to selector! + } else { + lhs.selectors.append((WeakRef(value: rhs.0), rhs.1)) + } +} + +public func -=(lhs: inout Multicast, rhs: (AnyObject, Selector)) { + if let index = lhs.selectors.index(where: { $0.0.value === rhs.0 && $0.1 == rhs.1 }) { + lhs.selectors.remove(at: index) + } +} + +public func -=(lhs: inout Multicast, rhs: AnyObject) { + lhs.selectors = lhs.selectors.filter { $0.0.value !== rhs } +} + +fileprivate struct WeakRef { + weak var value: AnyObject? +} From 1224e33e71f73786c868d4374abc2bf6ea18916c Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 11 Nov 2016 08:53:57 +1030 Subject: [PATCH 12/21] Add Multicast unit tests --- Example/FazeKit.xcodeproj/project.pbxproj | 4 ++ Example/Tests/MulticastTests.swift | 77 +++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 Example/Tests/MulticastTests.swift diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index 30e2bb4..2718302 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */; }; 78B6DD4BAF21BA4B263F3EF4 /* Pods_FazeKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DB0AD919FBE4556CA363D8B /* Pods_FazeKit_Tests.framework */; }; + C20FAFE21DD42EAA009E5C3F /* MulticastTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C20FAFE01DD42E7D009E5C3F /* MulticastTests.swift */; }; C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */; }; C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */; }; C2E94BAE1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */; }; @@ -45,6 +46,7 @@ 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewAdditionsTests.swift; sourceTree = ""; }; 739B56FA57C1D0E13427B629 /* Pods-FazeKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Tests/Pods-FazeKit_Tests.release.xcconfig"; sourceTree = ""; }; AE54F13DF076B827802B2E27 /* Pods-FazeKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FazeKit_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FazeKit_Example/Pods-FazeKit_Example.debug.xcconfig"; sourceTree = ""; }; + C20FAFE01DD42E7D009E5C3F /* MulticastTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MulticastTests.swift; sourceTree = ""; }; C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAdditionsTests.swift; sourceTree = ""; }; C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdditionsTests.swift; sourceTree = ""; }; C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessInfoAdditionsTests.swift; sourceTree = ""; }; @@ -129,6 +131,7 @@ children = ( C2B9A0361DD2DAB500AF4E04 /* CollectionAdditionsTests.swift */, C2B9A0301DD2941C00AF4E04 /* DateAdditionsTests.swift */, + C20FAFE01DD42E7D009E5C3F /* MulticastTests.swift */, C2E94BAD1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift */, 607FACEB1AFB9204008FA782 /* UIViewAdditionsTests.swift */, 607FACE91AFB9204008FA782 /* Supporting Files */, @@ -378,6 +381,7 @@ C2E94BAE1D62CDD5007A7A4C /* ProcessInfoAdditionsTests.swift in Sources */, 607FACEC1AFB9204008FA782 /* UIViewAdditionsTests.swift in Sources */, C2B9A0321DD29F9100AF4E04 /* DateAdditionsTests.swift in Sources */, + C20FAFE21DD42EAA009E5C3F /* MulticastTests.swift in Sources */, C2B9A0381DD2DAE500AF4E04 /* CollectionAdditionsTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/Tests/MulticastTests.swift b/Example/Tests/MulticastTests.swift new file mode 100644 index 0000000..254d1f1 --- /dev/null +++ b/Example/Tests/MulticastTests.swift @@ -0,0 +1,77 @@ +// +// Copyright 2016 NextFaze +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +// MulticastTests.swift +// FazeKit +// +// Created by swoolcock on 16/08/2016. +// + +import UIKit +import XCTest +import FazeKit + +class MulticastTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testMulticast() { + var multi = Multicast() + var temp: Int = 0 + + multi += { temp += 1 } + multi.invoke() + XCTAssertEqual(temp, 1) + + multi += { temp += 3 } + multi += { temp -= 10 } + multi.invoke() + XCTAssertEqual(temp, -5) + + let test = MulticastTestClass() + multi += (test, #selector(MulticastTestClass.testFunc1)) + multi.invoke() + XCTAssertEqual(temp, -11) + XCTAssertEqual(test.value, 10) + + multi += (test, #selector(MulticastTestClass.testFunc2)) + multi.invoke() + XCTAssertEqual(temp, -17) + XCTAssertEqual(test.value, 60) + + multi -= test + multi.invoke() + XCTAssertEqual(temp, -23) + XCTAssertEqual(test.value, 60) + } +} + +private class MulticastTestClass { + var value: Int = 0 + + @objc func testFunc1() { + value += 10 + } + + @objc func testFunc2() { + value += 40 + } +} From 639bb73a8545a6e06a6e0b215209909c0d876c5d Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 11 Nov 2016 10:30:43 +1030 Subject: [PATCH 13/21] Explicitly ignore return value of perform --- FazeKit/Classes/Multicast.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FazeKit/Classes/Multicast.swift b/FazeKit/Classes/Multicast.swift index 156097f..8e4ddec 100644 --- a/FazeKit/Classes/Multicast.swift +++ b/FazeKit/Classes/Multicast.swift @@ -35,7 +35,9 @@ open class Multicast { block() } for pairs in self.selectors { - pairs.0.value?.perform(pairs.1) + if let value = pairs.0.value, value.responds(to: pairs.1) { + _ = value.perform(pairs.1) + } } } } else { @@ -43,7 +45,7 @@ open class Multicast { block() } for pairs in self.selectors { - pairs.0.value?.perform(pairs.1) + _ = pairs.0.value?.perform(pairs.1) } } } From c8a7f84fb5948268c7d53e1360fedfc7e351893a Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 11 Nov 2016 10:48:05 +1030 Subject: [PATCH 14/21] Port some UIImage extension methods from NFAllocInit --- Example/Pods/Pods.xcodeproj/project.pbxproj | 4 + FazeKit/Classes/UIImageAdditions.swift | 127 ++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 FazeKit/Classes/UIImageAdditions.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 5ac90a6..f31c414 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 97D1E5959A6A6AD3083101B54EC863DB /* DateComponentAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358A02B2D078747F51B7D08DAA894B6B /* DateComponentAdditions.swift */; }; A36385A1F317D62E87EE7D5A8F21E911 /* UIViewAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F79D452925B39FBBCF569A722B2F00F /* UIViewAdditions.swift */; }; BAFA5C1A9A1BCC8128A101B35FC27A0F /* Pods-FazeKit_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2601B9E18AF362D1FA9762E15669E426 /* Pods-FazeKit_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C20FAFE41DD534A3009E5C3F /* UIImageAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C20FAFE31DD534A3009E5C3F /* UIImageAdditions.swift */; }; C2D50E9F1DD41DC3009517F4 /* Multicast.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D50E9E1DD41DC3009517F4 /* Multicast.swift */; }; CEFE6B1D1DD96BB2ECE4229B639DCA54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */; }; DF727BD7BA75C68423B2C104D288F7AC /* Pods-FazeKit_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F3C9BC2DA3BAC6164EE7AD012E3D24D /* Pods-FazeKit_Example-dummy.m */; }; @@ -78,6 +79,7 @@ A2A6FF208CEC4C2861F1E9D42D651453 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B6C175E93F3958F4BA9490F1A9D6C3B4 /* Pods-FazeKit_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FazeKit_Example-acknowledgements.plist"; sourceTree = ""; }; B9AC4DCD938604C35E5C7EF469BC86CB /* ProcessInfoAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProcessInfoAdditions.swift; sourceTree = ""; }; + C20FAFE31DD534A3009E5C3F /* UIImageAdditions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageAdditions.swift; sourceTree = ""; }; C2D50E9E1DD41DC3009517F4 /* Multicast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Multicast.swift; sourceTree = ""; }; CE2AD7B44607FA2CB0CD55F74EA74ECE /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D0EB5B784659EACA66F2D5917FBB8522 /* StringAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringAdditions.swift; sourceTree = ""; }; @@ -256,6 +258,7 @@ 0F0F08748B9CF253855FDB33B0ADCD94 /* UIScreenAdditions.swift */, 6F79D452925B39FBBCF569A722B2F00F /* UIViewAdditions.swift */, C2D50E9E1DD41DC3009517F4 /* Multicast.swift */, + C20FAFE31DD534A3009E5C3F /* UIImageAdditions.swift */, ); path = Classes; sourceTree = ""; @@ -400,6 +403,7 @@ 7F072CBAE02C90475DD540B8D8ED3C09 /* DateAdditions.swift in Sources */, 97D1E5959A6A6AD3083101B54EC863DB /* DateComponentAdditions.swift in Sources */, E699A32D308161067BC9A5861E01BF22 /* ProcessInfoAdditions.swift in Sources */, + C20FAFE41DD534A3009E5C3F /* UIImageAdditions.swift in Sources */, 64049AEA30380B2B26082F4CCDAD1947 /* StringAdditions.swift in Sources */, 3C34EFACBE8AC97A73A65A7A54758AD2 /* UIDeviceAdditions.swift in Sources */, 5535ED319233A70AC1C3C49280ECDEF2 /* UIResponderAdditions.swift in Sources */, diff --git a/FazeKit/Classes/UIImageAdditions.swift b/FazeKit/Classes/UIImageAdditions.swift new file mode 100644 index 0000000..d424ff9 --- /dev/null +++ b/FazeKit/Classes/UIImageAdditions.swift @@ -0,0 +1,127 @@ +// +// Copyright 2016 NextFaze +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +// UIImageAdditions.swift +// FazeKit +// +// Created by swoolcock on 11/11/2016. +// + +import Foundation +import UIKit + +extension UIImage { + public static func coloredImage(color: UIColor, size: CGSize? = nil) -> UIImage? { + let size = size ?? CGSize(width: 1.0, height: 1.0) + + UIGraphicsBeginImageContext(size) + guard let currentContext = UIGraphicsGetCurrentContext() else { return nil } + + currentContext.setFillColor(color.cgColor) + currentContext.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height)) + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return image + } + + public func imageByScalingAndRotating(maxSize: CGFloat) -> UIImage? { + guard let imageRef = self.cgImage else { return nil } + let width: CGFloat = CGFloat(imageRef.width) + let height: CGFloat = CGFloat(imageRef.height) + var transform: CGAffineTransform + var bounds = CGRect(x: 0, y: 0, width: width, height: height) + + if width > maxSize || height > maxSize { + let ratio = width / height + if ratio > 1 { + bounds.size.width = maxSize + bounds.size.height = bounds.size.width / ratio + } else { + bounds.size.height = maxSize + bounds.size.width = bounds.size.height * ratio + } + } + + let scaleRatio = bounds.size.width / width + let imageSize = CGSize(width: imageRef.width, height: imageRef.height) + let orientation = self.imageOrientation + + switch orientation { + case .up: // EXIF = 1 + transform = CGAffineTransform() + + case .upMirrored: // EXIF = 2 + transform = CGAffineTransform(translationX: imageSize.width, y: 0).scaledBy(x: -1, y: 1) + + case .down: // EXIF = 3 + transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height).rotated(by: CGFloat(M_PI)) + + case .downMirrored: // EXIF = 4 + transform = CGAffineTransform(translationX: 0, y: imageSize.height).scaledBy(x: 1, y: -1) + + case .leftMirrored: // EXIF = 5 + let boundsHeight = bounds.size.height + bounds.size.height = bounds.size.width + bounds.size.width = boundsHeight + transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width).scaledBy(x: -1, y: 1).rotated(by: CGFloat(3.0 * M_PI / 2.0)) + + case .left: // EXIF = 6 + let boundsHeight = bounds.size.height + bounds.size.height = bounds.size.width + bounds.size.width = boundsHeight + transform = CGAffineTransform(translationX: 0, y: imageSize.width).rotated(by: CGFloat(3.0 * M_PI / 2.0)) + + case .rightMirrored: // EXIF = 7 + let boundsHeight = bounds.size.height + bounds.size.height = bounds.size.width + bounds.size.width = boundsHeight + transform = CGAffineTransform(scaleX: -1, y: 1).rotated(by: CGFloat(M_PI / 2.0)) + + case .right: // EXIF = 8 + let boundsHeight = bounds.size.height + bounds.size.height = bounds.size.width + bounds.size.width = boundsHeight + transform = CGAffineTransform(translationX: imageSize.height, y: 0).rotated(by: CGFloat(M_PI / 2.0)) + + default: + // TODO: throw error + return nil + } + + UIGraphicsBeginImageContext(bounds.size) + guard let context = UIGraphicsGetCurrentContext() else { + // TODO: throw error + return nil + } + + if orientation == .right || orientation == .left { + context.scaleBy(x: -scaleRatio, y: scaleRatio) + context.translateBy(x: -height, y: 0) + } else { + context.scaleBy(x: scaleRatio, y: -scaleRatio) + context.translateBy(x: 0, y: -height) + } + + context.concatenate(transform) + + context.draw(imageRef, in: CGRect(x: 0, y: 0, width: width, height: height)) + let imageCopy = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return imageCopy + } +} From f4f09c95604467370c7d600945ace3fc8c900cba Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 11 Nov 2016 13:37:21 +1030 Subject: [PATCH 15/21] Remove unnecessary default switch case --- FazeKit/Classes/UIImageAdditions.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/FazeKit/Classes/UIImageAdditions.swift b/FazeKit/Classes/UIImageAdditions.swift index d424ff9..95bb056 100644 --- a/FazeKit/Classes/UIImageAdditions.swift +++ b/FazeKit/Classes/UIImageAdditions.swift @@ -96,10 +96,6 @@ extension UIImage { bounds.size.height = bounds.size.width bounds.size.width = boundsHeight transform = CGAffineTransform(translationX: imageSize.height, y: 0).rotated(by: CGFloat(M_PI / 2.0)) - - default: - // TODO: throw error - return nil } UIGraphicsBeginImageContext(bounds.size) From 1ca47908b5316b04fe35bdac035f322d79d37e83 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Mon, 14 Nov 2016 10:06:53 +1030 Subject: [PATCH 16/21] Add partitioning func to Collection that accepts a test block and returns two arrays as a tuple --- Example/Tests/CollectionAdditionsTests.swift | 7 +++++++ FazeKit/Classes/CollectionAdditions.swift | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Example/Tests/CollectionAdditionsTests.swift b/Example/Tests/CollectionAdditionsTests.swift index 9da4db1..52abfd3 100644 --- a/Example/Tests/CollectionAdditionsTests.swift +++ b/Example/Tests/CollectionAdditionsTests.swift @@ -44,6 +44,13 @@ class CollectionAdditionsTests: XCTestCase { XCTAssertNil(stringArray.firstMatch { $0[0] == "z" }, "Collection.firstMatch: found something we shouldn't") } + func testCollectionPartitioned() { + let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let parts = array.partitioned { $0 % 2 == 0 } + XCTAssertEqual(parts.0, [2, 4, 6, 8, 10], "Collection.partitioned: 'true' array did not match") + XCTAssertEqual(parts.1, [1, 3, 5, 7, 9], "Collection.partitioned: 'false' array did not match") + } + func testSequenceCategorise() { struct CategoriseTestStruct { var name: String diff --git a/FazeKit/Classes/CollectionAdditions.swift b/FazeKit/Classes/CollectionAdditions.swift index d4d4518..ff5c9ef 100644 --- a/FazeKit/Classes/CollectionAdditions.swift +++ b/FazeKit/Classes/CollectionAdditions.swift @@ -28,6 +28,19 @@ public extension Collection { guard let idx = try self.index(where: predicate) else { return nil } return self[idx] } + + public func partitioned(by comparisonBlock: (Iterator.Element) -> Bool) -> ([Iterator.Element], [Iterator.Element]) { + var trueArray: [Iterator.Element] = [] + var falseArray: [Iterator.Element] = [] + for item in self { + if comparisonBlock(item) { + trueArray.append(item) + } else { + falseArray.append(item) + } + } + return (trueArray, falseArray) + } } // Borrowed from: http://stackoverflow.com/a/31220067 @@ -64,4 +77,3 @@ public func +=(lhs: inout Dictionary, rhs: Dictionary(lhs: inout Dictionary, rhs: Dictionary) { rhs.forEach { lhs.removeValue(forKey: $0.key) } } - From 4202ed35527e11e4b7c9e95e45c7bb68374ae8df Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Mon, 14 Nov 2016 10:20:52 +1030 Subject: [PATCH 17/21] Update podspec to 1.0.0 for Swift 3 branch --- FazeKit.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FazeKit.podspec b/FazeKit.podspec index 2f72221..5efc674 100644 --- a/FazeKit.podspec +++ b/FazeKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'FazeKit' - s.version = '0.1.3' - s.summary = 'A collection of helper functions and extensions for Swift iOS apps' + s.version = '1.0.0' + s.summary = 'A collection of helper functions and extensions for Swift 3 iOS apps' s.description = 'A collection of extensions and convenience functions on Foundation, UIKit and other Cocoa Frameworks, built in Swift for iOS development' s.homepage = 'https://github.com/NextFaze/FazeKit' s.license = { :type => 'APACHE', :file => 'LICENSE' } From 2cefb12127dab2095d8854064abc059aa1db5aad Mon Sep 17 00:00:00 2001 From: Ricardo Santos Date: Thu, 24 Nov 2016 11:16:51 +1030 Subject: [PATCH 18/21] Update the podspec summary --- FazeKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FazeKit.podspec b/FazeKit.podspec index 5efc674..1b04778 100644 --- a/FazeKit.podspec +++ b/FazeKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'FazeKit' s.version = '1.0.0' - s.summary = 'A collection of helper functions and extensions for Swift 3 iOS apps' + s.summary = 'A collection of helper functions and extensions for Swift iOS apps' s.description = 'A collection of extensions and convenience functions on Foundation, UIKit and other Cocoa Frameworks, built in Swift for iOS development' s.homepage = 'https://github.com/NextFaze/FazeKit' s.license = { :type => 'APACHE', :file => 'LICENSE' } From 554278b8208688e12eebd21f58e1517347019f91 Mon Sep 17 00:00:00 2001 From: Ricardo Santos Date: Thu, 24 Nov 2016 11:44:25 +1030 Subject: [PATCH 19/21] Migrate device jailbreak detection code to Swift 3 --- FazeKit/Classes/UIDeviceAdditions.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/FazeKit/Classes/UIDeviceAdditions.swift b/FazeKit/Classes/UIDeviceAdditions.swift index c954d4a..b6942b4 100644 --- a/FazeKit/Classes/UIDeviceAdditions.swift +++ b/FazeKit/Classes/UIDeviceAdditions.swift @@ -55,10 +55,12 @@ public extension UIDevice { return false #else let filenames = ["/Applications/Cydia.app", "/Library/MobileSubstrate/MobileSubstrate.dylib", "/bin/bash", "/usr/sbin/sshd", "/etc/apt", "/usr/bin/ssh"] - let fileManager = NSFileManager.defaultManager() - guard filenames.firstMatch({fileManager.fileExistsAtPath($0)}) == nil else { return true } - guard let url = NSURL(string: "cydia://package/com.example.package") else { return false } - return UIApplication.sharedApplication().canOpenURL(url) + let fileManager = Foundation.FileManager.default + if filenames.first(where: {fileManager.fileExists(atPath: $0)}) != nil { + return true + } + guard let url = URL(string: "cydia://package/com.example.package") else { return false } + return UIApplication.shared.canOpenURL(url) #endif } } From 8d009fa3ac6cfd768f24a4f379d2d94304b255e8 Mon Sep 17 00:00:00 2001 From: Ricardo Santos Date: Thu, 24 Nov 2016 11:44:42 +1030 Subject: [PATCH 20/21] Set the development team to NextFaze --- Example/FazeKit.xcodeproj/project.pbxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Example/FazeKit.xcodeproj/project.pbxproj b/Example/FazeKit.xcodeproj/project.pbxproj index 2718302..4e08043 100644 --- a/Example/FazeKit.xcodeproj/project.pbxproj +++ b/Example/FazeKit.xcodeproj/project.pbxproj @@ -224,10 +224,12 @@ TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = B89H5L73N6; LastSwiftMigration = 0800; }; 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = B89H5L73N6; LastSwiftMigration = 0800; TestTargetID = 607FACCF1AFB9204008FA782; }; @@ -495,6 +497,7 @@ baseConfigurationReference = AE54F13DF076B827802B2E27 /* Pods-FazeKit_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = B89H5L73N6; INFOPLIST_FILE = FazeKit/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -510,6 +513,7 @@ baseConfigurationReference = 17B25E2129639E7E62C9740F /* Pods-FazeKit_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = B89H5L73N6; INFOPLIST_FILE = FazeKit/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -524,6 +528,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1E3B0E69CF2CF2930A6BA13A /* Pods-FazeKit_Tests.debug.xcconfig */; buildSettings = { + DEVELOPMENT_TEAM = B89H5L73N6; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", @@ -544,6 +549,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 739B56FA57C1D0E13427B629 /* Pods-FazeKit_Tests.release.xcconfig */; buildSettings = { + DEVELOPMENT_TEAM = B89H5L73N6; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", From 072dbf640331c0acfaf9c625bc7d7791368b61ca Mon Sep 17 00:00:00 2001 From: Ricardo Santos Date: Thu, 24 Nov 2016 12:10:13 +1030 Subject: [PATCH 21/21] Add a table view with the jailbroken status to the example app --- Example/FazeKit/MenuViewController.swift | 49 ++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/Example/FazeKit/MenuViewController.swift b/Example/FazeKit/MenuViewController.swift index 092ce09..df50d80 100644 --- a/Example/FazeKit/MenuViewController.swift +++ b/Example/FazeKit/MenuViewController.swift @@ -22,19 +22,62 @@ import UIKit import FazeKit -class MenuViewController: UIViewController { - +class MenuViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { + enum MenuItem { + case jailbreak + } + + let items: [MenuItem] = [.jailbreak] + + let tableView = UITableView() + static let cellReuseIdentifier = "MenuTableViewCell" + override func viewDidLoad() { super.viewDidLoad() self.title = "FazeKit" self.view.backgroundColor = UIColor.white + + self.tableView.dataSource = self + self.tableView.delegate = self + self.tableView.tableFooterView = UIView() + self.view.addSubview(self.tableView) } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + self.tableView.frame = self.view.bounds + } + override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. + print("WARNING: Memory warning.") } + // MARK: UITableViewDataSource + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.items.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: MenuViewController.cellReuseIdentifier) ?? UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: MenuViewController.cellReuseIdentifier) + + let item = self.items[indexPath.row] + switch item { + case .jailbreak: + cell.textLabel?.text = "Jailbroken" + cell.detailTextLabel?.text = UIDevice.isJailbroken() ? "Yes" : "No" + } + + return cell + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + } }