This file contains 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 NSObject { | |
/// A publisher for observing key-value changes when static swift KeyPaths are not available, such as when observing | |
/// `UserDefaults`. With this publisher only a `String` based keypath is required. | |
/// | |
/// Since this does not use static typed keypaths, we can not ensure that the value received from KVO is the type we | |
/// expect. So values that can not be converted to the expected value are ignored. | |
public struct StringKeyPathObservingPublisher<Value>: Publisher { | |
public typealias Output = Value |
This file contains 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 UIKit | |
open class SectionTitledDiffableDataSource<SectionIdentifierType, ItemIdentifierType>: UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> | |
where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable { | |
public typealias SectionTitleProvider = (UITableView, SectionIdentifierType) -> String? | |
open var sectionTitleProvider: SectionTitleProvider? | |
open var useSectionIndex: Bool = false | |
This file contains 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 UIKit | |
// I'm not sure how useful this is, but swift allows for a somewhat elegant closure base API for CATransation. | |
// Each argument if optional, so it can be omitted unless necessary. It's a little weird having the completion | |
// block come before the actions block, but this way the actions block can make sure of trailing closure syntax. | |
extension CATransaction { | |
static func transaction(duration: CFTimeInterval? = nil, | |
timingFunction: CAMediaTimingFunction? = nil, | |
disableActions: Bool? = nil, | |
completion: (() -> Void)? = nil, |
This file contains 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
extension KeyedDecodingContainer { | |
/// Some poorly designed APIs return JSON where the type is enclosed in quotes, which means it is interpreted as a String. | |
/// These two methods will attempt to decode the supplied type conforming to LosslessStringConvertible by first decoding the String | |
/// and then converting to the supplied type. | |
func decodeFromString<T>(_ type: T.Type, forKey key: K) throws -> T where T : LosslessStringConvertible { | |
let string = try decode(String.self, forKey: key) | |
guard let value = T(string) else { | |
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "decodeFromString failed") | |
} |