(by @andrestaltz)
If you prefer to watch video tutorials with live-coding, then check out this series I recorded with the same contents as in this article: Egghead.io - Introduction to Reactive Programming.
#!/bin/bash | |
appname="$1" | |
[ -z $appname ] && read -p "Application name : " appname | |
apppath=$(find ~/Library/Developer/CoreSimulator/Devices/ -name "$appname.app" -print -quit) | |
if [[ ! -z $apppath ]]; then | |
echo "Found path for $appname app" | |
echo -e "\033[1;30m$apppath\033[0m" | |
appbundle=$(osascript -e "id of app \"$apppath\"") |
extension JSONDecoder { | |
func decode<T: Decodable>(_ type: T.Type, from data: Data, keyedBy key: String?) throws -> T { | |
if let key = key { | |
// Pass the top level key to the decoder. | |
userInfo[.jsonDecoderRootKeyName] = key | |
let root = try decode(DecodableRoot<T>.self, from: data) | |
return root.value | |
} else { |
class FirebaseCoordinator { | |
static let shared = FirebaseCoordinator() | |
static let initialize: Void = { | |
/// We modify Google Firebase (and eventually Analytics) to load the mac-specific plist at runtime. | |
/// Google enforces that we have a file named "GoogleService-Info.plist" in the app resources. | |
/// This is unfortunate since we need two different files based on iOS and Mac version | |
/// One solution is a custom build step that copies in the correct file: | |
/// https://stackoverflow.com/questions/37615405/use-different-googleservice-info-plist-for-different-build-schemes | |
/// However, this is basically impossible since Catalyst doesn't set any custom build variables, so detection is extremely difficult. | |
/// We swizzle to modify the loading times. |
import Foundation | |
func findFiles(rootPath: String, suffix: String, ignoreDirs: Bool = true) -> [String]? { | |
var result = [String]() | |
let fileManager = FileManager.default | |
if let paths = fileManager.subpaths(atPath: rootPath) { | |
let swiftPaths = paths.filter { $0.hasSuffix(suffix) } | |
for path in swiftPaths { | |
var isDir : ObjCBool = false | |
let fullPath = (rootPath as NSString).appendingPathComponent(path) |
/* | |
* Adds the serialNumber property to the UIDevice class | |
* | |
* The implementation uses undocumented (for iOS) IOKit functions, | |
* so handle with caution and be prepared for nil. | |
*/ | |
#import <UIKit/UIDevice.h> | |
@interface UIDevice (serialNumber) |
import Foundation | |
private var throttleWorkItem: DispatchWorkItem? | |
private var lastDebounceCallTime: DispatchTime? | |
public extension DispatchQueue { | |
/** | |
- parameters: | |
- deadline: The timespan to delay a closure execution | |
- action: The closure to be executed |
(by @andrestaltz)
If you prefer to watch video tutorials with live-coding, then check out this series I recorded with the same contents as in this article: Egghead.io - Introduction to Reactive Programming.
# Uncomment this line to define a global platform for your project | |
# platform :ios, '9.0' | |
target 'YouApp' do | |
use_frameworks! | |
# Pods for YouApp | |
pod 'SwiftFramework', :branch => 'swift-2.3' | |
end |