How to use CommonCrypto in iOS

Issue #480 Use modulemap modulemap approach I use modulemap in my wrapper around CommonCrypto https://github.com/onmyway133/arcane, https://github.com/onmyway133/Reindeer For those getting header not found, please take a look https://github.com/onmyway133/Arcane/issues/4 or run xcode-select --install Make a folder CCommonCrypto containing module.modulemap module CCommonCrypto { header "/usr/include/CommonCrypto/CommonCrypto.h" export * } Go to Built Settings -> Import Paths ${SRCROOT}/Sources/CCommonCrypto Cocoapods with modulemap approach Here is the podspec https://github.com/onmyway133/Arcane/blob/master/Arcane.podspec s.source_files = 'Sources/**/*.swift' s.xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto' } s....

October 29, 2019 · 2 min · 217 words · Khoa

How to make ISO 8601 date in Swift

Issue #479 From ISO8601 spec, the problems are the representation and time zone ISO 8601 = year-month-day time timezone For date and time, there are basic (YYYYMMDD, hhmmss, ...) and extended format (YYYY-MM-DD, hh:mm:ss, ...) Time zone can be Zulu, offset or GMT Separator for date and time can be space, or T There are week format for date, but it is rarely used Timezone can be a lot of spaces after Second is optional Here are some valid strings...

October 29, 2019 · 3 min · 468 words · Khoa

How to configure test target in Xcode

Issue #478 This applies to Main targets App Framework Test targets Unit tests UI tests Examples Dependencies used Main target: Sugar Test target: Nimble, Quick Examples Cocoapods Carthage Notes Make sure test target can link to all the frameworks it needs. This includes frameworks that Test targets use, and possibly frameworks that Main target uses ! Remember to “Clean Build Folder” and “Clear Derived Data” so that you’re sure it works....

October 29, 2019 · 2 min · 394 words · Khoa

How to check platform versions in Swift

Issue #477 Mark APIs availability @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) public extension View { } Check platform #if canImport(UIKit) import UIKit #elseif canImport(OSX) import AppKit #endif In watchOS app, it still can import UIKit, so for only iOS usage, we need to use os check #if canImport(UIKit) && os(iOS) Check environment #if targetEnvironment(macCatalyst) print("UIKit running on macOS") #else print("Your regular code") #endif #if targetEnvironment(simulator) // your simulator code #else // your real device code #endif

October 29, 2019 · 1 min · 79 words · Khoa

How to use react-native link and CocoaPods

Issue #476 React Native comes with a default React library, and most CocoaPods libraries for React Native has React as a dependency pod, which causes the conflict https://github.com/react-native-community/react-native-svg/issues/621 https://stackoverflow.com/questions/45296994/difference-between-react-native-link-and-cocoapods https://github.com/onmyway133/notes/issues/486 https://github.com/facebook/react-native/pull/23563

October 29, 2019 · 1 min · 31 words · Khoa

How to flick using UIKit Dynamic in iOS

Issue #475 For a snack bar or image viewing, it’s handy to be able to just flick or toss to dismiss We can use UIKit Dynamic, which was introduced in iOS 7, to make this happen. Use UIPanGestureRecognizer to drag view around, UISnapBehavior to make view snap back to center if velocity is low, and UIPushBehavior to throw view in the direction of the gesture. import UIKit final class FlickHandler { private let viewToMove: UIView private let referenceView: UIView private var panGR: UIPanGestureRecognizer!...

October 23, 2019 · 2 min · 253 words · Khoa

How to use Swift package manager in watchOS

Issue #474 SPM Go to Project -> Swift Packages, add package. For example https://github.com/onmyway133/EasyStash Select your WatchKit Extension target, under Frameworks, Libraries and Embedded Content add the library CocoaPods If we use CocoaPods, then it needs to be in WatchKit Extension target 'MyApp WatchKit Extension' do use_frameworks! pod 'EasyStash', :git => 'https://github.com/onmyway133/EasyStash' end

October 23, 2019 · 1 min · 53 words · Khoa

How to use external display in iOS

Issue #473 Before iOS 13 Use UIScreen.didConnectNotification NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, object: nil, queue: nil) { (notification) in // Get the new screen information. let newScreen = notification.object as! UIScreen let screenDimensions = newScreen.bounds // Configure a window for the screen. let newWindow = UIWindow(frame: screenDimensions) newWindow.screen = newScreen // Install a custom root view controller in the window. self.configureAuxilliaryInterface(with: newWindow) // You must show the window explicitly. newWindow.isHidden = false // Save a reference to the window in a local array....

October 22, 2019 · 2 min · 291 words · Khoa

How to show error message like Snack Bar in iOS

Issue #472 Build error view Use convenient code from Omnia To make view height dynamic, pin UILabel to edges and center import UIKit final class ErrorMessageView: UIView { let box: UIView = { let view = UIView() view.backgroundColor = R.color.primary view.layer.cornerRadius = 6 return view }() let label: UILabel = { let label = UILabel() label.styleAsText() label.textColor = R.color.darkText label.numberOfLines = 0 return label }() override init(frame: CGRect) { super.init(frame: frame) setup() } required init?...

October 21, 2019 · 3 min · 459 words · Khoa

How to hide tab bar when push in iOS

Issue #471 let navigationController = UINavigationController(rootViewController: viewControllerA) navigationController.pushViewController(viewControllerB, animated: true) In view controller B, need to set hidesBottomBarWhenPushed in init final class ViewControllerB: UIViewController { let mainView = EditPaymentMethodView() var scenario: PaymentMethodScenario! init() { super.init(nibName: nil, bundle: nil) hidesBottomBarWhenPushed = true } required init?(coder: NSCoder) { fatalError() } }

October 18, 2019 · 1 min · 49 words · Khoa

How to add trailing image to UILabel in iOS

Issue #470 Use NSTextAttachment inside NSAttributedString extension UILabel { func addTrailing(image: UIImage) { let attachment = NSTextAttachment() attachment.image = image let attachmentString = NSAttributedString(attachment: attachment) let string = NSMutableAttributedString(string: self.text!, attributes: [:]) string.append(attachmentString) self.attributedText = string } }

October 17, 2019 · 1 min · 38 words · Khoa

How to handle different states in a screen in iOS

Issue #469 If there are lots of logics and states inside a screen, it is best to introduce parent and child container, and switch child depends on state. Each child acts as a State handler. In less logic case, we can introduce a Scenario class that holds the state. So the ViewController can be very slim. The thing with State is that all possible scenarios are clear and required to be handled...

October 17, 2019 · 1 min · 132 words · Khoa

How to reload data without using onAppear in SwiftUI in watchOS

Issue #468 From onAppeear Adds an action to perform when the view appears. In theory, this should be triggered every time this view appears. But in practice, it is only called when it is pushed on navigation stack, not when we return to it. So if user goes to a bookmark in a bookmark list, unbookmark an item and go back to the bookmark list, onAppear is not called again and the list is not updated....

October 17, 2019 · 2 min · 239 words · Khoa

How to use EnvironmentObject in SwiftUI for watchOS

Issue #467 Declare top dependencies in ExtensionDelegate class ExtensionDelegate: NSObject, WKExtensionDelegate { let storeContainer = StoreContainer() func applicationDidEnterBackground() { storeContainer.save() } } Reference that in HostingController. Note that we need to change from generic MainView to WKHostingController<AnyView> as environmentObject returns View protocol class HostingController: WKHostingController<AnyView> { var storeContainer: StoreContainer! override func awake(withContext context: Any?) { super.awake(withContext: context) self.storeContainer = (WKExtension.shared().delegate as! ExtensionDelegate).storeContainer } override var body: AnyView { return AnyView(MainView() ....

October 17, 2019 · 1 min · 179 words · Khoa

How to structure classes

Issue #466 iOS View Controller -> View Model | Logic Handler -> Data Handler -> Repo Android Activity -> Fragment -> View Model | Logic Handler -> Data Handler -> Repo

October 16, 2019 · 1 min · 31 words · Khoa

How to make generic store for Codable in Swift

Issue #465 Use EasyStash import EasyStash final class Store<T: Codable & ItemProtocol>: Codable { var items = [T]() func bookmark(item: T) { items.append(item) } func unbookmark(item: T) { guard let index = items.firstIndex(where: { $0.itemId == item.itemId }) else { return } items.remove(at: index) } func isBookmark(item: T) -> Bool { return items.contains(where: { $0.itemId == item.itemId }) } } import EasyStash final class StoreContainer { var food: Store<Food> static var shared = StoreContainer() let storage = try!...

October 14, 2019 · 1 min · 132 words · Khoa

How to declare escaping in completion in callback in Swift

Issue #464 typealias Completion = (Result<User, Error>) -> Void func validate(completion: @escaping Completion, then: (String, String, @escaping Completion) -> Void) {}

October 14, 2019 · 1 min · 21 words · Khoa

How to zoom to fit many coordinates in Google Maps in iOS

Issue #463 func zoom(location1: CLLocation, location2: CLLocation) { let bounds = GMSCoordinateBounds(coordinate: location1.coordinate, coordinate: location2.coordinate) let update = GMSCameraUpdate.fit(bounds, withPadding: 16) mapView.animate(with: update) }

October 14, 2019 · 1 min · 24 words · Khoa

How to use Codable to store preferences in Swift

Issue #462 Using object, we don’t need to care about nil vs false like in UserDefaults, our object is the source of truth class StoringHandler<T: Codable> { private let key: Storage.Keys private let storage = Deps.storage init(key: Storage.Keys) { self.key = key load() } var object: T? { didSet { if let object = object { try? storage.save(object: object, key: key) } else { try? storage.clear(key: key) } } } private func load() { self....

October 11, 2019 · 1 min · 123 words · Khoa

How to custom UIAlertController in iOS

Issue #461 With UIAlertController we can add buttons and textfields, and just that func addAction(UIAlertAction) func addTextField(configurationHandler: ((UITextField) -> Void)?) To add custom content to UIAlertController, there are some workarounds Add content onto UITextField Restyle UITextField and add custom content Subclass UIAlertController and handle UI in viewWillAppear By subclassing we can tweak the whole view hierarchy and listen to events like layout subviews, but this can be very fragile. Make custom UIViewController that looks like UIAlertController This is the correct way but takes too much time to imitate UIAlertController, and have to deal with UIVisualEffectView, resize view for different screen sizes and dark mode...

October 11, 2019 · 2 min · 222 words · Khoa