Last active
December 13, 2019 12:01
-
-
Save yonat/258449f6048fc92be196b12b658773e2 to your computer and use it in GitHub Desktop.
Random collection of Swift utilities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
extension Binding { | |
/// Execute block when value is changed. | |
/// | |
/// Example: | |
/// | |
/// Slider(value: $amount.didSet { print($0) }, in: 0...10) | |
func didSet(execute: @escaping (Value) ->Void) -> Binding { | |
return Binding( | |
get: { | |
return self.wrappedValue | |
}, | |
set: { | |
execute($0) | |
self.wrappedValue = $0 | |
} | |
) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Bundle { | |
func decode<T: Decodable>(_ file: String, dateFormat: String = "y-MM-dd") throws -> T { | |
guard let url = self.url(forResource: file, withExtension: nil) else { | |
throw NSError(code: 1, description: "Failed to locate \(file) in bundle.") | |
} | |
let data = try Data(contentsOf: url) | |
let decoder = JSONDecoder() | |
let formatter = DateFormatter() | |
formatter.dateFormat = dateFormat | |
decoder.dateDecodingStrategy = .formatted(formatter) | |
return try decoder.decode(T.self, from: data) | |
} | |
} | |
extension NSError { | |
convenience init(domain: String = "BundleDecodable", code: Int, description: String) { | |
self.init(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey: description]) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import CoreImage | |
import CoreImage.CIFilterBuiltins | |
import UIKit | |
extension CIFilter { | |
var displayName: String { | |
name | |
.dropFirst(2) // remove the "CI" from CISomeFilterName | |
.replacingOccurrences(of: "([a-z]|[A-Z]+)([A-Z])", with: "$1 $2", options: .regularExpression) // split CamelCase | |
} | |
func setInputImage(uiImage: UIImage) { | |
let beginImage = CIImage(image: uiImage) | |
setValue(beginImage, forKey: kCIInputImageKey) | |
} | |
func outputUIImage(context: CIContext = CIContext()) -> UIImage? { | |
guard let outputImage = outputImage, | |
let cgImage = context.createCGImage(outputImage, from: outputImage.extent) | |
else { return nil } | |
return UIImage(cgImage: cgImage) | |
} | |
func adjust(intensity: Float) { | |
if inputKeys.contains(kCIInputIntensityKey) { setValue(intensity, forKey: kCIInputIntensityKey) } | |
if inputKeys.contains(kCIInputRadiusKey) { setValue(intensity * 200, forKey: kCIInputRadiusKey) } | |
if inputKeys.contains(kCIInputScaleKey) { setValue(intensity * 10, forKey: kCIInputScaleKey) } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Optional where Wrapped: DefaultInit { | |
/// Returns the unwrapped value, or the default value if nil. | |
/// | |
/// Useful for binding optional values in SwiftUI. | |
/// | |
/// For example: `$pointAnnotation.title.unwrappedOrDefault` | |
var unwrappedOrDefault: Wrapped { | |
get { | |
self ?? Wrapped() | |
} | |
set { | |
self = newValue | |
} | |
} | |
} | |
protocol DefaultInit | |
{ | |
init() | |
} | |
extension Int: DefaultInit {} | |
extension Bool: DefaultInit {} | |
extension String: DefaultInit {} | |
extension Date: DefaultInit {} | |
extension Array: DefaultInit {} | |
extension Set: DefaultInit {} | |
extension Dictionary: DefaultInit {} | |
extension NSObject: DefaultInit {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
import SwifterSwift | |
extension Published { | |
/// Creates a publisher backed by a UserDefaults.standard value that is a property-list object | |
init(wrappedValue defaultValue: Value, userDefaultsKey key: String) { | |
let value = UserDefaults.standard.object(forKey: key) as? Value ?? defaultValue | |
self.init(initialValue: value) | |
thePublishedUserDefaultsSubscriptions[key] = projectedValue | |
.debounce(for: 1, scheduler: DispatchQueue.main) | |
.sink { UserDefaults.standard.set($0, forKey: key) } | |
} | |
} | |
extension Published where Value: Codable { | |
/// Creates a publisher backed by a UserDefaults.standard value that conforms to Codable | |
init(codableValue defaultValue: Value, userDefaultsKey key: String) { | |
let value = UserDefaults.standard.object(Value.self, with: key) ?? defaultValue | |
self.init(initialValue: value) | |
thePublishedUserDefaultsSubscriptions[key] = projectedValue | |
.debounce(for: 1, scheduler: DispatchQueue.main) | |
.sink { UserDefaults.standard.set(object: $0, forKey: key) } | |
} | |
} | |
private var thePublishedUserDefaultsSubscriptions: [String: AnyCancellable] = [:] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment