From 6531b89661ee5d3b0a752b0fb0718bf375e520ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:15:20 +0100 Subject: [PATCH 01/16] Add safe subscript on random access collections --- SafeSubscript.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 SafeSubscript.swift diff --git a/SafeSubscript.swift b/SafeSubscript.swift new file mode 100644 index 00000000..c2666825 --- /dev/null +++ b/SafeSubscript.swift @@ -0,0 +1,12 @@ +import Foundation + +/// Safe subscript for collections +public protocol SafeRandomAccessCollection: RandomAccessCollection { + subscript(safe index: Int) -> Iterator.Element? { get } +} + +extension Array: SafeRandomAccessCollection { + public subscript(safe index: Int) -> Iterator.Element? { + return indices ~= index ? self[index] : nil + } +} From d286d581dba67b7c909f3c81a7459959bbfbe8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:15:38 +0100 Subject: [PATCH 02/16] Add plus function to merge two dictionaries --- ACKategories/Classes/FoundationExtensions.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ACKategories/Classes/FoundationExtensions.swift b/ACKategories/Classes/FoundationExtensions.swift index 5b1d3c08..66986e82 100644 --- a/ACKategories/Classes/FoundationExtensions.swift +++ b/ACKategories/Classes/FoundationExtensions.swift @@ -61,3 +61,9 @@ extension NumberFormatter { return self.string(from: NSNumber(value: number)) } } + +func + (lhs: [Key: Value], rhs: [Key: Value]) -> [Key: Value] { + var result = lhs + for (k, v) in rhs { result.updateValue(v, forKey: k) } + return result +} From cdcca087b65e9d9095c58b845902154aca134673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:18:03 +0100 Subject: [PATCH 03/16] Add UITableView and UICollectionView dequeue extensions for headers/footers --- .../Classes/TableAndCollectionViewExtensions.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ACKategories/Classes/TableAndCollectionViewExtensions.swift b/ACKategories/Classes/TableAndCollectionViewExtensions.swift index 85783ab6..48acd185 100644 --- a/ACKategories/Classes/TableAndCollectionViewExtensions.swift +++ b/ACKategories/Classes/TableAndCollectionViewExtensions.swift @@ -3,14 +3,13 @@ import UIKit public protocol Reusable { } extension Reusable { - public static var reuseIdentifier: String { return NSStringFromClass(self as! AnyObject.Type) } - } extension UITableViewCell: Reusable { } +extension UITableViewHeaderFooterView: Reusable { } extension UICollectionReusableView: Reusable { } extension UITableView { @@ -18,6 +17,11 @@ extension UITableView { register(T.classForCoder(), forCellReuseIdentifier: T.reuseIdentifier) return dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as! T } + + public func dequeueHeaderFooterView() -> T where T: UITableViewHeaderFooterView { + register(T.classForCoder(), forHeaderFooterViewReuseIdentifier: T.reuseIdentifier) + return dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as! T + } } extension UICollectionView { @@ -25,4 +29,9 @@ extension UICollectionView { register(T.classForCoder(), forCellWithReuseIdentifier: T.reuseIdentifier) return dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T } + + public func dequeueSupplementaryView(ofKind kind: String, for indexPath: IndexPath) -> T where T: UICollectionReusableView { + register(T.classForCoder(), forSupplementaryViewOfKind: kind, withReuseIdentifier: T.reuseIdentifier) + return dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T + } } From 04d208927a86d040e069c5a8b9cb739c0f323301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:30:34 +0100 Subject: [PATCH 04/16] Add user defaults + deviceID --- UserDefaultsExtensions.swift | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 UserDefaultsExtensions.swift diff --git a/UserDefaultsExtensions.swift b/UserDefaultsExtensions.swift new file mode 100644 index 00000000..7d177e52 --- /dev/null +++ b/UserDefaultsExtensions.swift @@ -0,0 +1,20 @@ +import Foundation + +extension UserDefaults { + private enum Keys { + static let deviceID = "ud_device_id_b8cb6644-43fa-4bc4-a4f3-23f9e5d25c8f" + } + + public var deviceID: String { + if let result = string(forKey: Keys.deviceID) { + return result + } + + let newDeviceID = NSUUID().uuidString + + set(newDeviceID, forKey: Keys.deviceID) + synchronize() + + return newDeviceID + } +} From 7dea86f2864d025da799d1bdfdcf346281812335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:36:11 +0100 Subject: [PATCH 05/16] Update podspec --- ACKategories.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ACKategories.podspec b/ACKategories.podspec index 935d031f..450d7cb0 100644 --- a/ACKategories.podspec +++ b/ACKategories.podspec @@ -31,6 +31,6 @@ Tools, cocoa subclasses and extensions we love to use at Ackee. s.source_files = 'ACKategories/Classes/**/*' - # s.frameworks = 'UIKit', 'MapKit' + s.frameworks = 'UIKit' # s.dependency 'AFNetworking', '~> 2.3' end From ae8484d90781e5195b71e2303db19198ac692022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:57:40 +0100 Subject: [PATCH 06/16] Add Array.remove(object:) --- ACKategories/Classes/FoundationExtensions.swift | 10 +++++++++- .../Classes/SafeSubscript.swift | 0 ACKategories/Classes/UISearchBarExtensions.swift | 5 +++++ .../Classes/UserDefaultsExtensions.swift | 0 Example/Podfile.lock | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) rename SafeSubscript.swift => ACKategories/Classes/SafeSubscript.swift (100%) create mode 100644 ACKategories/Classes/UISearchBarExtensions.swift rename UserDefaultsExtensions.swift => ACKategories/Classes/UserDefaultsExtensions.swift (100%) diff --git a/ACKategories/Classes/FoundationExtensions.swift b/ACKategories/Classes/FoundationExtensions.swift index 66986e82..00663918 100644 --- a/ACKategories/Classes/FoundationExtensions.swift +++ b/ACKategories/Classes/FoundationExtensions.swift @@ -62,8 +62,16 @@ extension NumberFormatter { } } -func + (lhs: [Key: Value], rhs: [Key: Value]) -> [Key: Value] { +public func + (lhs: [Key: Value], rhs: [Key: Value]) -> [Key: Value] { var result = lhs for (k, v) in rhs { result.updateValue(v, forKey: k) } return result } + +extension Array where Element: Equatable { + public mutating func remove(object: Element) { + if let index = index(of: object) { + remove(at: index) + } + } +} diff --git a/SafeSubscript.swift b/ACKategories/Classes/SafeSubscript.swift similarity index 100% rename from SafeSubscript.swift rename to ACKategories/Classes/SafeSubscript.swift diff --git a/ACKategories/Classes/UISearchBarExtensions.swift b/ACKategories/Classes/UISearchBarExtensions.swift new file mode 100644 index 00000000..655c3c92 --- /dev/null +++ b/ACKategories/Classes/UISearchBarExtensions.swift @@ -0,0 +1,5 @@ +import UIKit + +public extension UISearchBar { + public var textField: UITextField! { return value(forKey: "searchField") as! UITextField } +} diff --git a/UserDefaultsExtensions.swift b/ACKategories/Classes/UserDefaultsExtensions.swift similarity index 100% rename from UserDefaultsExtensions.swift rename to ACKategories/Classes/UserDefaultsExtensions.swift diff --git a/Example/Podfile.lock b/Example/Podfile.lock index e7f8dfb2..bd40c1b6 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -13,7 +13,7 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - ACKategories: 139a869c79dcc12d6f6debd53898f3d169b8dd4e + ACKategories: 6634e7cbdaf5b3593367469c958ecfa24eaaec4b Nimble: bfe1f814edabba69ff145cb1283e04ed636a67f2 Quick: 5d290df1c69d5ee2f0729956dcf0fd9a30447eaa From c672dda10b5d79415dc6189088c8763a93476e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:58:36 +0100 Subject: [PATCH 07/16] Add Bundle extensions --- ACKategories/Classes/FoundationExtensions.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ACKategories/Classes/FoundationExtensions.swift b/ACKategories/Classes/FoundationExtensions.swift index 00663918..1ceea962 100644 --- a/ACKategories/Classes/FoundationExtensions.swift +++ b/ACKategories/Classes/FoundationExtensions.swift @@ -75,3 +75,17 @@ extension Array where Element: Equatable { } } } + +extension Bundle { + public var receiptData: Data? { + return appStoreReceiptURL.flatMap { try? Data(contentsOf: $0) } + } + + public var version: String? { + return infoDictionary?["CFBundleShortVersionString"] as? String + } + + public var buildNumber: Int? { + return (infoDictionary?["CFBundleVersion"] as? String).flatMap { Int($0) } + } +} From 0725cf34c847d4183566d106df87696676f00452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Thu, 30 Nov 2017 18:59:19 +0100 Subject: [PATCH 08/16] Add TimeInterval extensions --- .../Classes/FoundationExtensions.swift | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/ACKategories/Classes/FoundationExtensions.swift b/ACKategories/Classes/FoundationExtensions.swift index 1ceea962..9c53aa7c 100644 --- a/ACKategories/Classes/FoundationExtensions.swift +++ b/ACKategories/Classes/FoundationExtensions.swift @@ -77,15 +77,13 @@ extension Array where Element: Equatable { } extension Bundle { - public var receiptData: Data? { - return appStoreReceiptURL.flatMap { try? Data(contentsOf: $0) } - } - - public var version: String? { - return infoDictionary?["CFBundleShortVersionString"] as? String - } - - public var buildNumber: Int? { - return (infoDictionary?["CFBundleVersion"] as? String).flatMap { Int($0) } - } + public var receiptData: Data? { return appStoreReceiptURL.flatMap { try? Data(contentsOf: $0) } } + public var version: String? { return infoDictionary?["CFBundleShortVersionString"] as? String } + public var buildNumber: Int? { return (infoDictionary?["CFBundleVersion"] as? String).flatMap { Int($0) } } +} + +extension TimeInterval { + static var minute: TimeInterval { return TimeInterval(60) } + static var hour: TimeInterval { return minute * 60 } + static var day: TimeInterval { return hour * 24 } } From f875424e57bdd03a85690cb22aadd1a04dcba5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejn=C3=ADk?= Date: Fri, 1 Dec 2017 12:51:37 +0100 Subject: [PATCH 09/16] Fix TimeInterval extension accessors --- ACKategories/Classes/FoundationExtensions.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ACKategories/Classes/FoundationExtensions.swift b/ACKategories/Classes/FoundationExtensions.swift index 9c53aa7c..cfbc0242 100644 --- a/ACKategories/Classes/FoundationExtensions.swift +++ b/ACKategories/Classes/FoundationExtensions.swift @@ -83,7 +83,7 @@ extension Bundle { } extension TimeInterval { - static var minute: TimeInterval { return TimeInterval(60) } - static var hour: TimeInterval { return minute * 60 } - static var day: TimeInterval { return hour * 24 } + public static var minute: TimeInterval { return TimeInterval(60) } + public static var hour: TimeInterval { return minute * 60 } + public static var day: TimeInterval { return hour * 24 } } From e9d3a2881295f58ddc1444e5b13fa28338d7e1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Fri, 1 Dec 2017 16:25:43 +0100 Subject: [PATCH 10/16] Add UIImageExtensions to resize and fix orientation --- ACKategories/Classes/UIImageExtensions.swift | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ACKategories/Classes/UIImageExtensions.swift diff --git a/ACKategories/Classes/UIImageExtensions.swift b/ACKategories/Classes/UIImageExtensions.swift new file mode 100644 index 00000000..89e7856a --- /dev/null +++ b/ACKategories/Classes/UIImageExtensions.swift @@ -0,0 +1,34 @@ +import UIKit + +extension UIImage { + + // taken from http://stackoverflow.com/questions/10850184/ios-image-get-rotated-90-degree-after-saved-as-png-representation-data + public func fixedOrientation() -> UIImage { + guard imageOrientation != .up else { return self } + + UIGraphicsBeginImageContextWithOptions(size, false, scale) + draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) + let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + + return normalizedImage + } + + public func resized(maxDimension: CGFloat) -> UIImage? { + let isLandscape = size.width > size.height + + let newSize: CGSize + if isLandscape { + newSize = CGSize(width: maxDimension, height: (size.height / size.width) * maxDimension) + } else { + newSize = CGSize(width: (size.width / size.height) * maxDimension, height: maxDimension) + } + + UIGraphicsBeginImageContextWithOptions(newSize, false, 1) + draw(in: CGRect(origin: .zero, size: newSize)) + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return newImage + } + +} From 7096fe6901731f387edcc0e46e40cf3a77ea89e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Fri, 1 Dec 2017 16:35:02 +0100 Subject: [PATCH 11/16] Update Carthage project --- ACKategories.xcodeproj/project.pbxproj | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ACKategories.xcodeproj/project.pbxproj b/ACKategories.xcodeproj/project.pbxproj index c9026093..e10292c2 100644 --- a/ACKategories.xcodeproj/project.pbxproj +++ b/ACKategories.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 69A646BE1FD1AE1600BD4A98 /* SafeSubscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */; }; + 69A646BF1FD1AE1600BD4A98 /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */; }; + 69A646C01FD1AE1600BD4A98 /* UIImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */; }; + 69A646C11FD1AE1600BD4A98 /* UISearchBarExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */; }; + 69A646C21FD1AE1600BD4A98 /* UserDefaultsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */; }; D253FF901F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253FF871F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift */; }; D253FF911F0A65A80079215C /* Color+Extra.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253FF881F0A65A80079215C /* Color+Extra.swift */; }; D253FF921F0A65A80079215C /* Control+Blocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253FF891F0A65A80079215C /* Control+Blocks.swift */; }; @@ -17,6 +22,11 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeSubscript.swift; sourceTree = ""; }; + 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensions.swift; sourceTree = ""; }; + 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = ""; }; + 69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UISearchBarExtensions.swift; sourceTree = ""; }; + 69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtensions.swift; sourceTree = ""; }; D253FF781F0A65610079215C /* ACKategories.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ACKategories.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D253FF841F0A65A80079215C /* .gitkeep */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; D253FF871F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Buttons+FixedIntrinsicContentSize.swift"; sourceTree = ""; }; @@ -75,6 +85,11 @@ D253FF851F0A65A80079215C /* Classes */ = { isa = PBXGroup; children = ( + 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */, + 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */, + 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */, + 69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */, + 69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */, D253FF871F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift */, D253FF881F0A65A80079215C /* Color+Extra.swift */, D253FF891F0A65A80079215C /* Control+Blocks.swift */, @@ -167,11 +182,16 @@ files = ( D253FF911F0A65A80079215C /* Color+Extra.swift in Sources */, D253FF901F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift in Sources */, + 69A646C21FD1AE1600BD4A98 /* UserDefaultsExtensions.swift in Sources */, + 69A646C11FD1AE1600BD4A98 /* UISearchBarExtensions.swift in Sources */, D253FF961F0A65A80079215C /* UIControlEvents.swift in Sources */, D253FF921F0A65A80079215C /* Control+Blocks.swift in Sources */, + 69A646BE1FD1AE1600BD4A98 /* SafeSubscript.swift in Sources */, D253FF931F0A65A80079215C /* String+Extra.swift in Sources */, D253FF941F0A65A80079215C /* TableAndCollectionViewExtensions.swift in Sources */, + 69A646C01FD1AE1600BD4A98 /* UIImageExtensions.swift in Sources */, D253FF951F0A65A80079215C /* TableHeaderFooterView.swift in Sources */, + 69A646BF1FD1AE1600BD4A98 /* FoundationExtensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 905b16600ce9e3b224a1f7291eeb55ab47fb7594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejn=C3=ADk?= Date: Thu, 7 Dec 2017 13:36:43 +0100 Subject: [PATCH 12/16] Fix scale in UIImageExtensions --- ACKategories/Classes/UIImageExtensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ACKategories/Classes/UIImageExtensions.swift b/ACKategories/Classes/UIImageExtensions.swift index 89e7856a..39b6cd74 100644 --- a/ACKategories/Classes/UIImageExtensions.swift +++ b/ACKategories/Classes/UIImageExtensions.swift @@ -24,7 +24,7 @@ extension UIImage { newSize = CGSize(width: (size.width / size.height) * maxDimension, height: maxDimension) } - UIGraphicsBeginImageContextWithOptions(newSize, false, 1) + UIGraphicsBeginImageContextWithOptions(newSize, false, scale) draw(in: CGRect(origin: .zero, size: newSize)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() From 8ca8747254c4ff86afa52628c0973337f9795b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Fri, 8 Dec 2017 17:28:12 +0100 Subject: [PATCH 13/16] Add safe area compatibility extension for older systems --- UIViewController+SafeAreaCompat.swift | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 UIViewController+SafeAreaCompat.swift diff --git a/UIViewController+SafeAreaCompat.swift b/UIViewController+SafeAreaCompat.swift new file mode 100644 index 00000000..69e03d30 --- /dev/null +++ b/UIViewController+SafeAreaCompat.swift @@ -0,0 +1,30 @@ +import UIKit + +@available(iOS 9.0, *) +extension UIViewController { + private enum Keys { + static var safeArea: UInt8 = 0 + } + + /// Layout guide compatibility extension for iOS 11 safe area + /// + /// On iOS 11+ is the same as `view.safeAreaLayoutGuide`. + /// + /// On older systems it fallbacks to `topLayoutGuide.bottom` and `bottomLayoutGuide.top`, side constraints are equal to superview. + var safeArea: UILayoutGuide { + if #available(iOS 11.0, *) { + return view.safeAreaLayoutGuide + } else { + if let layoutGuide = objc_getAssociatedObject(self, &Keys.safeArea) as? UILayoutGuide { return layoutGuide } + + let layoutGuide = UILayoutGuide() + view.addLayoutGuide(layoutGuide) + layoutGuide.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true + layoutGuide.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true + layoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + layoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + objc_setAssociatedObject(self, &Keys.safeArea, layoutGuide, .OBJC_ASSOCIATION_ASSIGN) + return layoutGuide + } + } +} From bccac9262a7996681fa003df1368af7a8372fa2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Fri, 8 Dec 2017 17:34:00 +0100 Subject: [PATCH 14/16] Fix accessors --- UIViewController+SafeAreaCompat.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UIViewController+SafeAreaCompat.swift b/UIViewController+SafeAreaCompat.swift index 69e03d30..11401bd8 100644 --- a/UIViewController+SafeAreaCompat.swift +++ b/UIViewController+SafeAreaCompat.swift @@ -11,7 +11,7 @@ extension UIViewController { /// On iOS 11+ is the same as `view.safeAreaLayoutGuide`. /// /// On older systems it fallbacks to `topLayoutGuide.bottom` and `bottomLayoutGuide.top`, side constraints are equal to superview. - var safeArea: UILayoutGuide { + public var safeArea: UILayoutGuide { if #available(iOS 11.0, *) { return view.safeAreaLayoutGuide } else { From 1c6207cc6da11a82e3c6aadaebd62735a91b2dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Fri, 8 Dec 2017 17:37:14 +0100 Subject: [PATCH 15/16] Fix structure and carthage project file --- ACKategories.xcodeproj/project.pbxproj | 4 ++++ .../Classes/UIViewController+SafeAreaCompat.swift | 0 2 files changed, 4 insertions(+) rename UIViewController+SafeAreaCompat.swift => ACKategories/Classes/UIViewController+SafeAreaCompat.swift (100%) diff --git a/ACKategories.xcodeproj/project.pbxproj b/ACKategories.xcodeproj/project.pbxproj index e10292c2..64fd93f3 100644 --- a/ACKategories.xcodeproj/project.pbxproj +++ b/ACKategories.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 6964365B1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */; }; 69A646BE1FD1AE1600BD4A98 /* SafeSubscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */; }; 69A646BF1FD1AE1600BD4A98 /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */; }; 69A646C01FD1AE1600BD4A98 /* UIImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */; }; @@ -22,6 +23,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+SafeAreaCompat.swift"; sourceTree = ""; }; 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeSubscript.swift; sourceTree = ""; }; 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensions.swift; sourceTree = ""; }; 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = ""; }; @@ -85,6 +87,7 @@ D253FF851F0A65A80079215C /* Classes */ = { isa = PBXGroup; children = ( + 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */, 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */, 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */, 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */, @@ -182,6 +185,7 @@ files = ( D253FF911F0A65A80079215C /* Color+Extra.swift in Sources */, D253FF901F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift in Sources */, + 6964365B1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift in Sources */, 69A646C21FD1AE1600BD4A98 /* UserDefaultsExtensions.swift in Sources */, 69A646C11FD1AE1600BD4A98 /* UISearchBarExtensions.swift in Sources */, D253FF961F0A65A80079215C /* UIControlEvents.swift in Sources */, diff --git a/UIViewController+SafeAreaCompat.swift b/ACKategories/Classes/UIViewController+SafeAreaCompat.swift similarity index 100% rename from UIViewController+SafeAreaCompat.swift rename to ACKategories/Classes/UIViewController+SafeAreaCompat.swift From 5e45a62455a999aaf5595e927996b407c66d3eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Olejni=CC=81k?= Date: Sat, 9 Dec 2017 00:28:00 +0100 Subject: [PATCH 16/16] Add conditional assignment operator --- ACKategories.xcodeproj/project.pbxproj | 16 ++++++++++------ ACKategories/Classes/ConditionalAssignment.swift | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 ACKategories/Classes/ConditionalAssignment.swift diff --git a/ACKategories.xcodeproj/project.pbxproj b/ACKategories.xcodeproj/project.pbxproj index 64fd93f3..17280515 100644 --- a/ACKategories.xcodeproj/project.pbxproj +++ b/ACKategories.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 6964365B1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */; }; + 6965AEE91FDB5752001A08C5 /* ConditionalAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6965AEE81FDB5752001A08C5 /* ConditionalAssignment.swift */; }; 69A646BE1FD1AE1600BD4A98 /* SafeSubscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */; }; 69A646BF1FD1AE1600BD4A98 /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */; }; 69A646C01FD1AE1600BD4A98 /* UIImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */; }; @@ -24,6 +25,7 @@ /* Begin PBXFileReference section */ 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+SafeAreaCompat.swift"; sourceTree = ""; }; + 6965AEE81FDB5752001A08C5 /* ConditionalAssignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConditionalAssignment.swift; sourceTree = ""; }; 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeSubscript.swift; sourceTree = ""; }; 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensions.swift; sourceTree = ""; }; 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = ""; }; @@ -87,19 +89,20 @@ D253FF851F0A65A80079215C /* Classes */ = { isa = PBXGroup; children = ( - 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */, - 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */, - 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */, - 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */, - 69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */, - 69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */, D253FF871F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift */, D253FF881F0A65A80079215C /* Color+Extra.swift */, + 6965AEE81FDB5752001A08C5 /* ConditionalAssignment.swift */, D253FF891F0A65A80079215C /* Control+Blocks.swift */, + 69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */, + 69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */, D253FF8A1F0A65A80079215C /* String+Extra.swift */, D253FF8B1F0A65A80079215C /* TableAndCollectionViewExtensions.swift */, D253FF8C1F0A65A80079215C /* TableHeaderFooterView.swift */, D253FF8D1F0A65A80079215C /* UIControlEvents.swift */, + 69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */, + 69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */, + 6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */, + 69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */, ); path = Classes; sourceTree = ""; @@ -196,6 +199,7 @@ 69A646C01FD1AE1600BD4A98 /* UIImageExtensions.swift in Sources */, D253FF951F0A65A80079215C /* TableHeaderFooterView.swift in Sources */, 69A646BF1FD1AE1600BD4A98 /* FoundationExtensions.swift in Sources */, + 6965AEE91FDB5752001A08C5 /* ConditionalAssignment.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ACKategories/Classes/ConditionalAssignment.swift b/ACKategories/Classes/ConditionalAssignment.swift new file mode 100644 index 00000000..5d2f92ab --- /dev/null +++ b/ACKategories/Classes/ConditionalAssignment.swift @@ -0,0 +1,15 @@ +import Foundation + +precedencegroup ConditionalAssignmentPrecedence { + associativity: left + assignment: true + higherThan: AssignmentPrecedence +} + +infix operator =?: ConditionalAssignmentPrecedence + +public func =?(variable: inout T, value: T?) { + if let v = value { + variable = v + } +}