Skip to content

Commit

Permalink
Merge pull request #17 from AckeeCZ/jo/new_stuff
Browse files Browse the repository at this point in the history
New stuff
  • Loading branch information
pteasima authored Dec 14, 2017
2 parents a801a3e + 5e45a62 commit 11e0aea
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 4 deletions.
2 changes: 1 addition & 1 deletion ACKategories.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
28 changes: 28 additions & 0 deletions ACKategories.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
objects = {

/* 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 */; };
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 */; };
Expand All @@ -17,6 +24,13 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
6964365A1FDAF72A000D5CAA /* UIViewController+SafeAreaCompat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+SafeAreaCompat.swift"; sourceTree = "<group>"; };
6965AEE81FDB5752001A08C5 /* ConditionalAssignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConditionalAssignment.swift; sourceTree = "<group>"; };
69A646B91FD1AE1600BD4A98 /* SafeSubscript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeSubscript.swift; sourceTree = "<group>"; };
69A646BA1FD1AE1600BD4A98 /* FoundationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensions.swift; sourceTree = "<group>"; };
69A646BB1FD1AE1600BD4A98 /* UIImageExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = "<group>"; };
69A646BC1FD1AE1600BD4A98 /* UISearchBarExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UISearchBarExtensions.swift; sourceTree = "<group>"; };
69A646BD1FD1AE1600BD4A98 /* UserDefaultsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtensions.swift; sourceTree = "<group>"; };
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 = "<group>"; };
D253FF871F0A65A80079215C /* Buttons+FixedIntrinsicContentSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Buttons+FixedIntrinsicContentSize.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -77,11 +91,18 @@
children = (
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 = "<group>";
Expand Down Expand Up @@ -167,11 +188,18 @@
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 */,
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 */,
6965AEE91FDB5752001A08C5 /* ConditionalAssignment.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
15 changes: 15 additions & 0 deletions ACKategories/Classes/ConditionalAssignment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

precedencegroup ConditionalAssignmentPrecedence {
associativity: left
assignment: true
higherThan: AssignmentPrecedence
}

infix operator =?: ConditionalAssignmentPrecedence

public func =?<T>(variable: inout T, value: T?) {
if let v = value {
variable = v
}
}
26 changes: 26 additions & 0 deletions ACKategories/Classes/FoundationExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,29 @@ extension NumberFormatter {
return self.string(from: NSNumber(value: number))
}
}

public func +<Key, Value> (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)
}
}
}

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) } }
}

extension TimeInterval {
public static var minute: TimeInterval { return TimeInterval(60) }
public static var hour: TimeInterval { return minute * 60 }
public static var day: TimeInterval { return hour * 24 }
}
12 changes: 12 additions & 0 deletions ACKategories/Classes/SafeSubscript.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
13 changes: 11 additions & 2 deletions ACKategories/Classes/TableAndCollectionViewExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,35 @@ 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 {
public func dequeueCell<T>(for indexPath: IndexPath) -> T where T: UITableViewCell {
register(T.classForCoder(), forCellReuseIdentifier: T.reuseIdentifier)
return dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as! T
}

public func dequeueHeaderFooterView<T>() -> T where T: UITableViewHeaderFooterView {
register(T.classForCoder(), forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
return dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as! T
}
}

extension UICollectionView {
public func dequeueCell<T>(for indexPath: IndexPath) -> T where T: UICollectionViewCell {
register(T.classForCoder(), forCellWithReuseIdentifier: T.reuseIdentifier)
return dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T
}

public func dequeueSupplementaryView<T>(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
}
}
34 changes: 34 additions & 0 deletions ACKategories/Classes/UIImageExtensions.swift
Original file line number Diff line number Diff line change
@@ -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, scale)
draw(in: CGRect(origin: .zero, size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}

}
5 changes: 5 additions & 0 deletions ACKategories/Classes/UISearchBarExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import UIKit

public extension UISearchBar {
public var textField: UITextField! { return value(forKey: "searchField") as! UITextField }
}
30 changes: 30 additions & 0 deletions ACKategories/Classes/UIViewController+SafeAreaCompat.swift
Original file line number Diff line number Diff line change
@@ -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.
public 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
}
}
}
20 changes: 20 additions & 0 deletions ACKategories/Classes/UserDefaultsExtensions.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
2 changes: 1 addition & 1 deletion Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ EXTERNAL SOURCES:
:path: ../

SPEC CHECKSUMS:
ACKategories: 139a869c79dcc12d6f6debd53898f3d169b8dd4e
ACKategories: 6634e7cbdaf5b3593367469c958ecfa24eaaec4b
Nimble: bfe1f814edabba69ff145cb1283e04ed636a67f2
Quick: 5d290df1c69d5ee2f0729956dcf0fd9a30447eaa

Expand Down

0 comments on commit 11e0aea

Please sign in to comment.