Skip to content

Instantly share code, notes, and snippets.

View stinger's full-sized avatar

Ilian Konchev stinger

View GitHub Profile
@stinger
stinger / Bindings.swift
Last active October 18, 2018 11:25
KVO-driven model bindings
extension NSObjectProtocol where Self: NSObject {
func observe<Value>(_ keyPath: KeyPath<Self, Value>, onChange: @escaping (Value) -> ()) -> NSKeyValueObservation {
return observe(keyPath, options: [.initial, .new]) { _, change in
// TODO: change.newValue should never be `nil`, but when observing an optional property that's set to `nil`, then change.newValue is `nil` instead of `Optional(nil)`. This is the bug report for this: https://bugs.swift.org/browse/SR-6066
guard let newValue = change.newValue else { return }
onChange(newValue)
}
}
func bind<Value, Target>(_ sourceKeyPath: KeyPath<Self, Value>, to target: Target, at targetKeyPath: ReferenceWritableKeyPath<Target, Value>) -> NSKeyValueObservation {
@stinger
stinger / dynamicMemberLookup.swift
Created June 12, 2018 13:09
Swift 4.2 dynamicMemberLookup example
@dynamicMemberLookup
class Person {
let name: String
let age: Int
private let details: [String: String]
init(name: String, age: Int, details: [String: String]) {
self.name = name
self.age = age
self.details = details
@stinger
stinger / DateFormattingPlayground.swift
Created November 14, 2018 15:35
Functional date formatting
import Foundation
extension Date {
typealias FormattedString = (DateFormatter) -> String
func formatted(by format: String) -> FormattedString {
return { formatter in
formatter.dateFormat = format
return formatter.string(from: self)
}
import UIKit
extension UIImage {
/**
Resizes the image to width x height and converts it to an RGB CVPixelBuffer.
*/
public func pixelBuffer(width: Int, height: Int) -> CVPixelBuffer? {
var maybePixelBuffer: CVPixelBuffer?
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
@stinger
stinger / Iff.swift
Created June 17, 2019 07:28 — forked from sergdort/Iff.swift
Iff and Some operators for #SwiftUI. Inspired on some stuff we use in [Bento](). It lets you chain modifiers instead of doing "if - else" dance 🚀
extension View {
func iff(_ condition: Bool, _ modifier: (Self) -> AnyView) -> AnyView {
if condition {
return modifier(self).eraseToAnyView()
}
return eraseToAnyView()
}
func some<Value>(_ optional: Value?, modifier: (Value, Self) -> AnyView) -> some View {
guard let value = optional else {
@stinger
stinger / CombineFetcher.swift
Last active January 28, 2023 18:07
Combine - fetching data using URLSession publishers
import Foundation
import Combine
enum APIError: Error, LocalizedError {
case unknown, apiError(reason: String)
var errorDescription: String? {
switch self {
case .unknown:
return "Unknown error"
@stinger
stinger / CombineFetcherAndDecoder.swift
Last active February 17, 2024 02:07
Combine - fetching and decoding JSON data
import Foundation
import Combine
enum APIError: Error, LocalizedError {
case unknown, apiError(reason: String), parserError(reason: String)
var errorDescription: String? {
switch self {
case .unknown:
return "Unknown error"
@stinger
stinger / CombineMockClient.swift
Created July 3, 2019 12:26
Mock data loader using Combine
import Foundation
import Combine
enum APIError: Error, LocalizedError {
case unknownError
case unknownURL
case unknownData
case parserError(reason: String)
case apiError(reason: String)
@stinger
stinger / stinger.zsh-theme
Created July 3, 2019 14:58
My oh-my-zsh theme
function prompt_char {
if [ $UID -eq 0 ]; then echo "#"; else echo $; fi
}
PROMPT='%(!.%{$fg_bold[red]%}.%{$fg_bold[cyan]%}%n@)%m:%{$fg_bold[green]%}%(!.%~.%1~)%{$fg_bold[yellow]%} $(git_prompt_info)%{$fg_bold[cyan]%}$(prompt_char)%{$reset_color%} '
ZSH_THEME_GIT_PROMPT_PREFIX="("
ZSH_THEME_GIT_PROMPT_SUFFIX=") "
@stinger
stinger / String+IsValid.swift
Last active December 28, 2020 11:06
Functional String validation
func validate<T: Codable>(_ validator: @escaping (T) -> Bool) -> (T) -> Bool {
return { input in
return validator(input)
}
}
enum StringValidator: CustomStringConvertible {
case isNotEmpty
case lengthIn(ClosedRange<Int>)