Skip to content

Instantly share code, notes, and snippets.

@manmal
manmal / Versionable+EnumeratedVersion.swift
Last active June 10, 2020 21:42
Variation on @merowing_'s Versionable: https://github.com/krzysztofzablocki/Versionable - adds enumerated versions
// This is a variation on @merowing_'s Versionable: https://github.com/krzysztofzablocki/Versionable
// It's an attempt to add enumerated versions. Together with CaseIterable conformance, this makes
// it harder to "forget" to add migrations for version bumps. Not super happy with the namings, but it
// should be enough to get the idea.
//
// Modifications made:
// - New protocol `VersionType`
// - Versionable.Version is `VersionType`
// - Replaced Versionable.migrations with Versionable.migrate(to:)
// - decode() fetches migrations via Versionable.Version.allCases and Versionable.migrate(to:)
@manmal
manmal / Playground.swift
Created December 9, 2019 14:39
Demo of weak vs strong capturing in closures
import Foundation
import PlaygroundSupport
import UIKit
class M {
var a = ""
func x() { self.a = "A" }
@manmal
manmal / erase.sh
Created November 13, 2019 06:37
Force-purge free space from a drive in macOS
diskutil secureErase freespace 0 /dev/disk1s1
@manmal
manmal / Date+TimeAgo.swift
Created July 22, 2019 11:45
Date+TimeAgo.swift
extension Date {
var timeAgo: String {
let calendar = Calendar.current
let now = Date()
let earliest = self < now ? self : now
let latest = self > now ? self : now
let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfMonth, .month, .year, .second]
let components: DateComponents = calendar.dateComponents(unitFlags, from: earliest, to: latest)
import Foundation
import UIKit
class CachedItemHeightDatasource: NSObject, UITableViewDelegate, UITableViewDataSource {
var heightAtIndexPath: [IndexPath: CGFloat] = [:]
let tableView: UITableView
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return heightAtIndexPath[indexPath] ?? UITableViewAutomaticDimension
@manmal
manmal / Synchronized.swift
Last active December 27, 2018 18:23
Thread safety for properties and executions in general — Swift 4.2
import Foundation
/// Thread-safe value wrapper with asynchronous setter and
/// synchronous getter.
///
/// Some discussion: https://twitter.com/manuelmaly/status/1077885584939630593?s=20
public final class SynchronizedProperty<T> {
public typealias DidSet = Bool
public let executer: SynchronizedExecuter
@manmal
manmal / TableViewCellProducer.swift
Created December 3, 2018 09:38
TableViewCellProducer
public protocol TableViewCellDequeueIdentifier: CustomStringConvertible { }
public enum TableViewCellProducer<UITVC: UITableViewCell>: Equatable {
case classAndIdentifier(class: UITVC.Type, identifier: TableViewCellDequeueIdentifier, configure: (UITVC) -> ())
case generator(() -> UITVC)
func cell(tableView: UITableView) -> UITVC {
switch self {
case let .classAndIdentifier(clazz, identifier, configure):
@manmal
manmal / HTMLAttributedStringCache.swift
Last active February 4, 2018 10:42
Cache HTML strings as NSAttributedStrings, with their font face and color changed (keeping traits like bold/italic). Makes use of the awesome locking extensions at https://gist.github.com/einsteinx2/00b9ebd962f3a0f6c9e758f842e4c6f9
import Foundation
import UIKit
// Uses locking from https://gist.github.com/einsteinx2/00b9ebd962f3a0f6c9e758f842e4c6f9
class HTMLAttributedStringCache {
private let lock = NSLock()
private struct Key: Hashable {
@manmal
manmal / Corestore+Ensembles.swift
Last active September 4, 2018 15:34
CoreStore + Ensembles - Merge data from ensembles.io into CoreStore such that the mainContext (and its listeners) notice changes to previously unregistered objects
// mark - CDEPersistentStoreEnsembleDelegate
public func persistentStoreEnsemble(_ ensemble: CDEPersistentStoreEnsemble, didSaveMergeChangesWith notification: Notification) {
func mergeChanges(stack: DataStack) {
assert(Thread.isMainThread)
let mainContext = stack.internalContext()
@manmal
manmal / SortedArrayDiff.swift
Last active April 6, 2017 10:41
Creates a diff for two sorted arrays that transforms one array into the other. CAUTION: I'm not sure yet whether contents of "changed" are correct in all cases. Please notify me at @manuelmaly if you see any issues.
import Foundation
extension Array where Element:Equatable {
typealias ArrayDiffResult = (added: [(Index, Element)], removed: [(Index, Element)], changed: [(Index, Element)])
// Inspired by: http://stackoverflow.com/q/3476672/458603
// compare has to return .orderedSame if the identity of the element is the same,
// even if the element's values have changed.
func diff(other: Array<Element>, compare: ((Element, Element) -> ComparisonResult), preSorted: Bool) -> ArrayDiffResult {