Skip to content

Instantly share code, notes, and snippets.

@yonat
Last active December 13, 2019 12:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yonat/258449f6048fc92be196b12b658773e2 to your computer and use it in GitHub Desktop.
Save yonat/258449f6048fc92be196b12b658773e2 to your computer and use it in GitHub Desktop.
Random collection of Swift utilities
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
}
)
}
}
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])
}
}
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) }
}
}
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 {}
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