Swift Watch and Run
This is my Swift "run on change" watcher script.
#!/bin/sh
# swiftWatchAndRun
if [ $# -ne 1 ]; then
echo "Use like this:"
echo " $0 filename-to-watch"
exit 1
fi
if which fswatch >/dev/null; then
echo "Watching swift file $1"
while true; do fswatch --one-event $1 >/dev/null && echo "----------------"; echo `date +"%m-%d-%y %I:%M%p"`; echo "----------------" && swift $1; sleep 0.1; done
else
echo "You might need to run: brew install fswatch"
fi
Posted on April 22nd, 2019
WeakArray for the Last Time (Swift 4.2)
I am obsessed with weak arrays. If you're trying to use multiple "protocolized" delegates, you need a weakly-held array of delegates.
This one started with this great article and expanded from there. Big thanks to Varindra Hart for the wise counsel as always.
@objc public protocol Equalable: class {
@objc func isEqual(_ object: Any?) -> Bool
}
/// Store AnyObject subclasses weakly
/// * Note: if you wish to use a protocol, it must:
/// - be marked with `@objc`
/// - have all methods marked with `@objc`
/// - refine Equalable
public struct WeakArray<Element: Equalable> {
private var items: [WeakBox<Element>] = []
public init(_ elements: [Element]? = nil) {
guard let elements = elements else { return }
items = elements.map { WeakBox($0) }
}
public mutating func append(_ newElement: Element) {
let box = WeakBox(newElement)
items.append(box)
}
public mutating func remove(_ element: Element) {
items.removeAll { item in
return item.unbox?.isEqual(element) ?? false
}
}
public var unboxed: [Element] {
let filtered = items.filter { $0.unbox != nil }
return filtered.compactMap { $0.unbox }
}
public var boxedCount: Int {
return items.count
}
}
extension WeakArray: Collection {
public var startIndex: Int { return items.startIndex }
public var endIndex: Int { return items.endIndex }
public subscript(_ index: Int) -> Element? {
return items[index].unbox
}
public func index(after idx: Int) -> Int {
return items.index(after: idx)
}
}
private final class WeakBox<T: Equalable> {
weak var unbox: T?
init(_ value: T) {
unbox = value
}
}
The need to have your protocol conform to @objc is a bug in Swift. See the StackOverflow question about this.
Posted on November 18th, 2018
Modifiable: Modify and Assign without Temporary Variables
This Protocol & Extension allow you to assign and modify all in one line.
I've been meaning to write this for a long time. It's working in Swift 4.1. It's definitely a tiny bit tricky, definitely not necessary, and perhaps too cute to be worth it. But it is cute!
import UIKit
/// Modifiable, Dan Rosenstark 2018, inspired from:
/// https://medium.com/@victor.pavlychko/using-self-in-swift-class-extensions-6421dab02587
protocol Modifiable {}
extension NSObject: Modifiable {}
extension Modifiable {
func modify(block: (Self)->()) -> Self {
block(self)
return self
}
}
/// examples
let view = UIView().modify { $0.backgroundColor = .green }
print(view.backgroundColor == UIColor.green)
Posted on June 16th, 2018
Xcodebuild: Valid Destinations on OSX?
To get a list of valid destinations, specify an erroneous key-value pair and xcodebuild will spit out the combinations that work.
List Destinations Command
xcodebuild test -destination 'platform=iOS Simulator' -workspace Register.xcworkspace -scheme ThatTestTarget
Output Example
Available destinations for the "ThatTestTarget" scheme:
{ platform:iOS Simulator, id:145A9B7E-B336-4819-8059-2FFEC408E05E, OS:11.1, name:iPad (5th generation) }
{ platform:iOS Simulator, id:69ABAF6F-ADA3-4E38-AC97-D71001447663, OS:9.3, name:iPad 2 }
{ platform:iOS Simulator, id:550E2F18-406D-4586-84BB-E48F1D704F27, OS:10.3.1, name:iPad Air }
{ platform:iOS Simulator, id:94734F1C-775F-40FA-9015-8196C08805EF, OS:11.1, name:iPad Air }
{ platform:iOS Simulator, id:1DB953DD-CD97-4EC7-8006-BCF01DF3E63F, OS:11.1, name:iPad Air 2 }
{ platform:iOS Simulator, id:DE3072DA-2E31-423D-9D77-220626F8B90A, OS:11.1, name:iPad Pro (9.7-inch) }
{ platform:iOS Simulator, id:3B5D18DB-13B5-4F28-B654-7D2ECDD1F6F0, OS:11.1, name:iPad Pro (10.5-inch) }
{ platform:iOS Simulator, id:A4225E3A-512C-4F42-ADD9-1E7E448C4D27, OS:11.1, name:iPad Pro (12.9-inch) }
{ platform:iOS Simulator, id:684FF1BA-8784-4B7C-B4E5-5231772F0FAC, OS:11.1, name:iPad Pro (12.9-inch) (2nd generation) }
Change Colons for Equals Signs, Remove Spaces, Ignore the ID
So if you want to use this destination:
platform:iOS Simulator, id:684FF1BA-8784-4B7C-B4E5-5231772F0FAC, OS:11.1, name:iPad Pro (12.9-inch) (2nd generation)
Change the colons for commas, remove the spaces, remove the ID, so you get this string:
platform=iOS Simulator,OS=11.1,name=iPad Pro (12.9-inch) (2nd generation)
Then the entire command would be:
xcodebuild test -destination 'platform=iOS Simulator,OS=11.1,name=iPad Pro (12.9-inch) (2nd generation)' -workspace Register.xcworkspace -scheme ThatTestTarget
From my StackOverflow Answer here
Posted on January 8th, 2018
Square in Autolayout in Swift 3/4

Posted on December 13th, 2017
How I Survive on Any Unix (Bash)
export EDITOR=nanoPS1='\h:\w\$ '
export EDITOR=nanofunction parse_git_dirty {[[ $(git status 2> /dev/null | tail -n1) != "nothing to commit, working tree clean" ]] && echo "*"}function parse_git_branch {git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/(\1$(parse_git_dirty))/"}export PS1='\h:\[\033[1;33m\]\w\[\033[0m\]$(parse_git_branch)$ '
Posted on December 5th, 2017
Solution for No Optionals in Swift String Interpolation
Posted on November 6th, 2017
My Time/Datestamp Applescript
Posted on October 13th, 2017
Just Because It Compiles: More Notes from Swift 3 Upgrade
This is the method signature for the superclass:
public func sendRequest<T: Request>(request: T, handler: (Result<T.Response, Error>) -> Void) -> NSURLSessionDataTask? {
and this is in the subclass
override func sendRequest<T : RequestType>(request: T, handler: (Result<T.Response, PayLib.Error>) -> Void) -> NSURLSessionDataTask? {
and in Swift 3 this got translated to be the same, except for some minor changes:
open func sendRequest<T: Request>(_ request: T, handler: @escaping (Result<T.Response, Error>) -> Void) -> URLSessionDataTask? {
Subclass:
override func sendRequest<T : RequestType>(_ request: T, handler: @escaping (Result<T.Response, PayLib.Error>) -> Void) -> URLSessionDataTask? ```
Now that was good enough for Swift 2. In Swift 3, a call to this method resulted in a crash with no interesting information.
The reason was the mismatch between RequestType and Request (RequestType is the protocol which the Request Protocol extends). So the fix was merely to have the signatures match exactly.
override func sendRequest<T : Request>(_ request: T, handler: @escaping (Result<T.Response, PayLib.Error>) -> Void) -> URLSessionDataTask? {
I'm not sure that there's a point here, except that: Just because Xcode likes it, it compiles and it works in Swift 2 doesn't mean that it won't cause a runtime crash in Swift 3. Or something like that: check everything by hand/eye!
Posted on October 5th, 2017