How to workaround URLSession issue in watchOS 6.1.1

Issue #577 https://stackoverflow.com/questions/59724731/class-avassetdownloadtask-is-implemented-in-both-cfnetwork-and-avfoundation objc[45250]: Class AVAssetDownloadTask is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CFNetwork.framework/CFNetwork (0x4ddd0ec) and /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AVFoundation.framework/AVFoundation (0x16aea494). One of the two will be used. Which one is undefined. objc[45250]: Class AVAssetDownloadURLSession is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CFNetwork.framework/CFNetwork (0x4dddd44) and /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AVFoundation.framework/AVFoundation (0x16aea4bc). One of the two will be used. Which one is undefined. Then URLSession stops working. 2020-01-13 22:50:12.430920+0100 MyAppWatch WatchKit Extension[45250:2099229] Task <3CECDE81-59B9-4EDE-A4ED-1BA173646037>.<1> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://myapp.com/def.json, NSErrorFailingURLStringKey=https://myapp.com/def.json, NSLocalizedDescription=cancelled} The workaround is to remove Combine based API, and use completion block....

January 13, 2020 · 1 min · Khoa Pham

How to generate XCTest test methods

Issue #576 Code See Spek Override testInvocations to specify test methods https://developer.apple.com/documentation/xctest/xctestcase/1496271-testinvocations Returns an array of invocations representing each test method in the test case. Because testInvocations is unavailable in Swift, we need to use ObjC #import "include/SpekHelperTestCase.h" @implementation SpekHelperTestCase - (instancetype)init { self = [super initWithInvocation: nil]; return self; } + (NSArray<NSInvocation *> *)testInvocations { NSArray<NSString *> *selectorStrings = [self spekGenerateTestMethodNames]; NSMutableArray<NSInvocation *> *invocations = [NSMutableArray arrayWithCapacity:selectorStrings....

January 12, 2020 · 2 min · Khoa Pham

How to use ObjC in Swift Package Manager

Issue #575 Create Objc target http://ankit.im/swift/2016/05/21/creating-objc-cpp-packages-with-swift-package-manager/ Check runtime Check for example _runtime(_ObjC) or os(macOS if you plan to use platform specific feature https://github.com/Quick/Quick/blob/master/Package.swift https://github.com/Quick/Quick/pull/687/files For example, in test we use XCTest which is run via Xcode and is a macOS framework, so we need to check for os(macOS) Note that in Objc framework, the header files must be in include folder targets: { var targets: [Target] = [ ....

January 11, 2020 · 1 min · Khoa Pham

How to expression cast type in lldb in Swit

Issue #574 expr -l Swift -- import UIKit expr -l Swift -- let $collectionView = unsafeBitCast(0x7fddd8180000, to: UICollectionView.self) expr -l Swift -- $collectionView.safeAreaInsets

January 10, 2020 · 1 min · Khoa Pham

How to disable implicit decoration view animation in UICollectionView

Issue #569 From documentation https://developer.apple.com/documentation/uikit/uicollectionviewlayout/1617726-initiallayoutattributesforappear This method is called after the prepare(forCollectionViewUpdates:) method and before the finalizeCollectionViewUpdates() method for any decoration views that are about to be inserted. Your implementation should return the layout information that describes the initial position and state of the view. The collection view uses this information as the starting point for any animations. (The end point of the animation is the view’s new location in the collection view....

January 6, 2020 · 1 min · Khoa Pham

How to make simple tracker via swizzling in Swift

Issue #568 Code EasyTracker Swizzle viewDidAppear https://github.com/onmyway133/EasyTracker/blob/master/Sources/Trackers.swift import UIKit var mapping: [String: (UIViewController) -> Void] = [:] var hasSwizzled = false public func track<T: UIViewController>(_ type: T.Type, block: @escaping (T) -> Void) { let original = #selector(UIViewController.viewDidAppear(_:)) let swizled = #selector(UIViewController.trackers_viewDidAppear(_:)) if !hasSwizzled { swizzle(kClass: UIViewController.self, originalSelector: original, swizzledSelector: swizled) hasSwizzled = true } mapping[NSStringFromClass(type)] = { controller in if let controller = controller as? T { block(controller) } } } extension UIViewController { func trackers_viewDidAppear(_ animated: Bool) { trackers_viewDidAppear(animated) let string = NSStringFromClass(type(of: self)) mapping[string]?...

January 4, 2020 · 1 min · Khoa Pham

How to make simple adapter for delegate and datasource for UICollectionView and UITableView

Issue #567 Code Upstream Make open Adapter https://github.com/onmyway133/Upstream import UIKit public protocol AdapterDelegate: class { /// Apply model to view func configure(model: Any, view: UIView, indexPath: IndexPath) /// Handle view selection func select(model: Any) /// Size the view func size(model: Any, containerSize: CGSize) -> CGSize } /// Act as DataSource and Delegate for UICollectionView, UITableView open class Adapter: NSObject, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDataSource, UITableViewDelegate { public var sections: [Section] = [] public weak var collectionView: UICollectionView?...

January 4, 2020 · 5 min · Khoa Pham

How to make progress HUD in Swift

Issue #566 Code FantasticDisplay Create a container that has blur effect public class HUDContainer: UIVisualEffectView, AnimationAware { private let innerContentView: UIView & AnimationAware public let label = UILabel() public var text: String? { didSet { label.text = text label.sizeToFit() label.isHidden = text == nil } } public init(contentView: UIView & AnimationAware) { self.innerContentView = contentView super.init(effect: UIBlurEffect(style: .light)) self.contentView.addSubview(innerContentView) self.contentView.addSubview(label) innerContentView.pinEdgesToSuperview() configure() } public required init?(coder aDecoder: NSCoder) { fatalError() } public func configure() { layer....

January 4, 2020 · 4 min · Khoa Pham

How to specify year in date formatter in Swift

Issue #565 Serious Security: The decade-ending Y2K bug that wasnt Challenges of DateFormatters

January 3, 2020 · 1 min · Khoa Pham

How to build static site using Publish

Issue #564 Code https://github.com/JohnSundell/publish Example https://github.com/pumaswift/pumaswift.github.io Steps Step 1: Create executable swift package init --type executable Step 2: Edit package // swift-tools-version:5.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "PumaSwiftWeb", dependencies: [ .package(url: "https://github.com/johnsundell/publish.git", from: "0.1.0") ], targets: [ .target( name: "PumaSwiftWeb", dependencies: [ "Publish" ] ) ] ) Step 3: Double click Package.swift, Xcode opens that in a generated project Step 4: Declare website....

January 2, 2020 · 1 min · Khoa Pham

How to use Timer and RunLoop in Swift

Issue #562 Run Timer in command line application Timer.scheduledTimer(withTimeInterval: seconds, repeats: false, block: { _ in completion(.success(())) }) RunLoop.current.run() Read more https://www.hackingwithswift.com/articles/117/the-ultimate-guide-to-timer https://learnappmaking.com/timer-swift-how-to/

January 1, 2020 · 1 min · Khoa Pham

How to send message from bot to Slack in Swift

Issue #560 Create a bot https://slack.com/intl/en-no/help/articles/115005265703-create-a-bot-for-your-workspace https://api.slack.com/bot-users#setup-events-api https://api.slack.com/bot-users#installing-bot Post message After adding bot to workspace, we’ll get OAuth Access Token and Bot User OAuth Access Token. Use Bot User OAuth Access Token to test drive bot message sending https://api.slack.com/methods/chat.postMessage/test The request url is like https://slack.com/api/chat.postMessage?token=xoxb-7212342835698-890815481123-abcdGgDEFfm2joQs1Vj5mABC&channel=random&text=hello&pretty=1 Code from Puma import Foundation public class Slack { public var name: String = "Send message to Slack" public var isEnabled = true private var message: Message?...

December 30, 2019 · 2 min · Khoa Pham

How to parse xcrun simctl devices

Issue #559 public class GetDestinations { public init() {} public func getAvailable(workflow: Workflow) throws -> [Destination] { let processHandler = DefaultProcessHandler(filter: { $0.starts(with: "name=") }) let string = try CommandLine().runBash( workflow: workflow, program: "xcrun simctl", arguments: [ "list", "devices", "-j" ], processHandler: processHandler ) guard let data = string.data(using: .utf8) else { throw PumaError.invalid } let response: Response = try JSONDecoder().decode(Response.self, from: data) let devicesWithOS: [DeviceWithOS] = response.devices.flatMap({ key, value in return value....

December 28, 2019 · 2 min · Khoa Pham

How to parse xcrun instruments devices

Issue #558 public class GetDestinations { public init() {} public func getAvailable(workflow: Workflow) throws -> [Destination] { let processHandler = DefaultProcessHandler(filter: { $0.starts(with: "name=") }) let string = try CommandLine().runBash( workflow: workflow, program: "xcrun instruments", arguments: [ "-s", "devices" ], processHandler: processHandler ) // Ex: iPad Air (11.0.1) [7A5EAD29-D870-49FB-9A9B-C81079620AC9] (Simulator) let destinations: [Destination] = try string .split(separator: "\n") .map({ String($0) }) .filter({ try $0.hasPattern(pattern: #"\[.+\]"#) }) .compactMap({ (line) -> Destination? in parse(line) }) return destinations } func parse(_ line: String) -> Destination?...

December 28, 2019 · 2 min · Khoa Pham

How to generate xml in Swift

Issue #556 Instead of learning XMLParser, we can make a lightweight version import Foundation public protocol XmlItem { func toLines() -> [String] } public struct XmlString: XmlItem { public let key: String public let value: String public init(key: String, value: String) { self.key = key self.value = value } public func toLines() -> [String] { return [ "<key>\(key)</key>", "<string>\(value)</string>" ] as [String] } } public struct XmlBool: XmlItem { public let key: String public let value: Bool public init(key: String, value: Bool) { self....

December 27, 2019 · 2 min · Khoa Pham

How to use KVO in Swift

Issue #554 A class must inherit from NSObject, and we have 3 ways to trigger property change Use setValue(value: AnyObject?, forKey key: String) from NSKeyValueCoding class MyObjectToObserve: NSObject { var myDate = NSDate() func updateDate() { setValue(NSDate(), forKey: "myDate") } } Use willChangeValueForKey and didChangeValueForKey from NSKeyValueObserving class MyObjectToObserve: NSObject { var myDate = NSDate() func updateDate() { willChangeValueForKey("myDate") myDate = NSDate() didChangeValueForKey("myDate") } } Use dynamic. See Swift Type Compatibility...

December 22, 2019 · 1 min · Khoa Pham

How to use precondition and assert in Swift

Issue #553 Read Swift asserts - the missing manual debug release release function -Onone -O -Ounchecked assert() YES NO NO assertionFailure() YES NO NO** precondition() YES YES NO preconditionFailure() YES YES YES** fatalError()* YES YES YES And from Interesting discussions on Swift Evolution – assert: checking your own code for internal errors – precondition: for checking that your clients have given you valid arguments. Read more https://stackoverflow....

December 22, 2019 · 1 min · Khoa Pham

How to use regular expression in Swift

Issue #551 Find matches import Foundation public extension String { func matches(pattern: String) throws -> [String] { let regex = try NSRegularExpression(pattern: pattern) let results = regex.matches(in: self, options: [], range: NSRange(self.startIndex..., in: self)) return results.compactMap({ result in if let range = Range(result.range, in: self) { return String(self[range]) } else { return nil } }) } func hasPattern(pattern: String) throws -> Bool { return try !matches(pattern: pattern).isEmpty } } func testRegex() throws { let string = "iPad Air (11....

December 20, 2019 · 1 min · Khoa Pham

How to keep command line tool running with async in Swift

Issue #549 Use Semaphore public class Sequence: Task { public func run(workflow: Workflow, completion: @escaping TaskCompletion) { let semaphore = DispatchSemaphore(value: 0) runFirst(tasks: tasks, workflow: workflow, completion: { result in completion(result) semaphore.signal() }) semaphore.wait() } } public class Concurrent: Task { public func run(workflow: Workflow, completion: @escaping (Result<(), Error>) -> Void) { var runTaskCount = 0 let taskCount = tasks.count let semaphore = DispatchSemaphore(value: 0) tasks.forEach { task in task.run(workflow: workflow, completion: { _ in self....

December 18, 2019 · 1 min · Khoa Pham

How to sync an async function in Swift

Issue #547 func sync<T>(_ work: (@escaping ([T]) -> Void) -> Void) -> [T] { let semaphore = DispatchSemaphore(value: 1) var results = [T]() work { values in results = values semaphore.signal() } return results } sync({ completion in service.load(completion) })

December 18, 2019 · 1 min · Khoa Pham