Skip to content

Instantly share code, notes, and snippets.

@joshavant
joshavant / KeychainCoding.swift
Created April 19, 2016 22:17
Swifty Keychain Abstraction
protocol KeychainCoding {
init?(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer)
func encodeToKeychain(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer) throws
}
extension KeychainCoding where Self: NSCoding, Self: InstanceInitializable {
init?(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer) {
do {
if let data = try keychain.get(identifier) {
let unarchivedInstance = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! Self
@joshavant
joshavant / RawRepresentableExtensions.swift
Created April 21, 2016 20:59
RawRepresentable, meet NSCoding
extension RawRepresentable where Self: NSCoding {
init?(rawValue: NSData) {
if let instance = NSKeyedUnarchiver.unarchiveObjectWithData(rawValue) as? Self {
self = instance
} else {
return nil
}
}
var rawValue: NSData {
@joshavant
joshavant / gist:1a134eb4209af7e8b0befc79c76fec8a
Created April 26, 2016 00:20
In-Air Internet Connectivity Profile
$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=36 time=721.833 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=36 time=847.672 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=36 time=742.803 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=36 time=599.856 ms
Request timeout for icmp_seq 4
64 bytes from 8.8.8.8: icmp_seq=4 ttl=36 time=1066.764 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=36 time=647.643 ms
64 bytes from 8.8.8.8: icmp_seq=6 ttl=36 time=668.060 ms
@joshavant
joshavant / String+Replacement.swift
Created May 1, 2016 00:19
Replace characters from set with replacement string
import Foundation
extension String {
func replaceCharactersFromSet(characterSet: NSCharacterSet, replacementString: String) -> String {
let scanner = NSScanner(string: self)
scanner.charactersToBeSkipped = nil
let sanitizedString = NSMutableString(capacity: self.characters.count)
while(!scanner.atEnd) {
enum ApplicationSupportFileServiceError: ErrorType {
case WriteFailed
case CouldntGetApplicationSupportDirectoryURL // it would be super weird for this to happen
}
typealias ApplicationSupportFileServiceKeyType = String // value represents a filename
struct ApplicationSupportFileService: KeyedItemPersistenceServiceable {
let fileManager: NSFileManager
@joshavant
joshavant / AppDelegate.swift
Last active June 11, 2016 15:11
Optimal Push Notification Pattern
class AppDelegate: UIResponder, UIApplicationDelegate {
private var currentUserNotificationTypes: UIUserNotificationType = .None
private func processUpdatedUserNotificationSettings(application: UIApplication, currentUserNotificationSettings notificationSettings: UIUserNotificationSettings?) {
let newUserNotificationTypes: UIUserNotificationType = notificationSettings?.types ?? .None
// only performs actions if the current value has a delta with the new value
if currentUserNotificationTypes.contains(.Alert) != newUserNotificationTypes.contains(.Alert) {
self.currentUserNotificationTypes = newUserNotificationTypes
// 1. Implement URLSession:task:didReceiveChallenge:completionHandler:. (Be sure to call the completion handler with NSURLSessionAuthChallengeDisposition.PerformDefaultHandling and a nil NSURLCredential.)
// 2. Set a breakpoint in the callback + trigger an authentication challenge at runtime
// 3. In the debugger, inspect the callback's `challenge.protectionSpace` argument for the values to put in the following lines of code...
// 4. Put the following lines of code somewhere before your network requests (i.e. AppDelegate area, or other)
let basicAuthCredentials = NSURLCredential(user: "username", password: "password", persistence: .Permanent)
let foobarHttpsProtectionSpace = NSURLProtectionSpace(host: "foo.bar.com", port: 443, protocol: "https", realm: "This Probably Has A Value, Get It From The Delegate Callback", authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
NSURLCredentialStorage.sharedCredentialStorage().setDefaultCredential(basicAuthCredentials, forProtectionSpace: apidevHttpsProtectionSpace
if context == &FooKVOContext {
// .CGSizeValue can cause a sneaky segfault here, because it will execute on ALL keyPaths (not just "contentSize")
if let newContentSize = change?[NSKeyValueChangeNewKey]?.CGSizeValue() where keyPath == "contentSize" {
// do things
}
} else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
(lldb) po self.tableView.visibleCells
0 elements
(lldb) po self.tableView.indexPathsForVisibleRows
▿ Optional<Array<NSIndexPath>>
▿ Some : 3 elements
- [0] : <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}
- [1] : <NSIndexPath: 0xc000000000200016> {length = 2, path = 0 - 1}
- [2] : <NSIndexPath: 0xc000000000400016> {length = 2, path = 0 - 2}
@joshavant
joshavant / UITextView+HeightCalculation.swift
Created July 21, 2016 03:00
UITextView Height Calculation
extension UITextView {
// Note: This will trigger a text rendering!
func calculateViewHeightWithCurrentWidth() -> CGFloat {
let textWidth = self.frame.width -
self.textContainerInset.left -
self.textContainerInset.right -
self.textContainer.lineFragmentPadding * 2.0 -
self.contentInset.left -
self.contentInset.right