Skip to content

Instantly share code, notes, and snippets.

View mortenbekditlevsen's full-sized avatar

Morten Bek Ditlevsen mortenbekditlevsen

View GitHub Profile
@mortenbekditlevsen
mortenbekditlevsen / UIDevice+DetectBlur.h
Last active February 23, 2017 16:35
Detecting whether or not the UIVisualEffectView is available and supports the UIBlurEffect
//
// UIDevice+DetectBlur.h
// BlurTest
//
// Created by Morten Ditlevsen on 28/01/15.
// Copyright (c) 2015 Mojo Apps. All rights reserved.
//
#import <UIKit/UIKit.h>
@mortenbekditlevsen
mortenbekditlevsen / phantom.swift
Created March 26, 2018 07:17
Example of using Phantom generics to create a hierarchy reflecting a firebase rtdb tree structure
import Foundation
// Note: This code is inspired by the objc.io talk: https://talk.objc.io/episodes/S01E71-type-safe-file-paths-with-phantom-types
// Background: For a project, we were already using Firebase along with RxSwift.
// For this purpose we have a protocol, NetworkServiceType providing the API to the Firebase functionality. The reason for this is that we could potentially switch to a different technology in case we wanted to.
// In this playground I will just write dummy-implementations for NetworkServiceType, FirebaseService and for the RxSwift Observable since these are separate concerns.
// Dummy 'Observable'
enum Observable<T> {
I am including parts of the IR code generated for i386 / iphone simulator (where the crash occurs) followed by corresponding parts fom x86_64 (non-crashing):
The crash was due to missing / garbage witness table data for the _JSONStringKeyedDictionaryEncodableMarker, so this is what I have been focusing on - skipping a few occurrances that I somehow don't think are relevant.
i386:
%T10Foundation36_JSONStringDictionaryEncodableMarker33_12768CA107A31EF2DCE034FD75B541C9LLP = type { [12 x i8], %swift.type*, i8** }
x64_64:
%T10Foundation36_JSONStringDictionaryEncodableMarker33_12768CA107A31EF2DCE034FD75B541C9LLP = type { [24 x i8], %swift.type*, i8** }
import Foundation
import FirebaseDatabase
import Result
public typealias DecodeResult<T> = Result<T, DecodeError>
public enum DecodeError: Error {
case noValuePresent
case conversionError(Error)
}
// Instead of this ...
ref.observeSingleEvent(of: .value) { snapshot in
guard snapshot.exists() else {
/* HANDLE ERROR */
}
guard let value = snapshot.value else {
/* HANDLE ERROR */
}
guard let product = Product(usingMyCustomJSONConversion: value) else {
public extension DatabaseQuery {
func observeSingleEvent<T>(of type: DataEventType,
with block: @escaping (DecodeResult<T>) -> Void)
where T: Decodable {
observeSingleEvent(of: type) { snap in
block(snap.decoded())
}
}
func observe<T>(eventType: DataEventType,
public extension DatabaseReference {
func setValue<T>(_ value: T) throws where T: Encodable {
let encoder = StructureEncoder()
self.setValue(try encoder.encode(value))
}
}
struct Product: Decodable {
let name: String
let price: Decimal
}
let p = Product(name: "Coffee", price: 2.50)
try ref.setValue(p)
// So from the Objc.io talk, we learn about a way of representing filesystem paths that can point to either files or directories.
// Internally, these are represented as an array of path elements. Let's do that too:
public struct Path<Element> {
private var components: [String]
fileprivate func append<T>(_ args: String ...) -> Path<T> {
return Path<T>(components + args)
}
//
// FirebaseService.swift
// SwiftyFirebase
//
// Created by Morten Bek Ditlevsen on 29/07/2018.
// Copyright © 2018 Ka-ching. All rights reserved.
//
import FirebaseDatabase
import Foundation