How to add padding to left right view in UITextField

Issue #536 extension UITextField { func setLeftView(_ view: UIView, padding: CGFloat) { view.translatesAutoresizingMaskIntoConstraints = true let outerView = UIView() outerView.translatesAutoresizingMaskIntoConstraints = false outerView.addSubview(view) outerView.frame = CGRect( origin: .zero, size: CGSize( width: view.frame.size.width + padding, height: view.frame.size.height + padding ) ) view.center = CGPoint( x: outerView.bounds.size.width / 2, y: outerView.bounds.size.height / 2 ) leftView = outerView } }

December 10, 2019 · 1 min · Khoa Pham

How to set date color in UIDatePicker in iOS 13

Issue #535 datePicker.setValue(UIColor.green, forKey: "textColor") datePicker.setValue(false, forKey: "highlightsToday") In iOS 14 if #available(iOS 14.0, *) { datePicker.preferredDatePickerStyle = .wheels datePicker.tintColor = UIColor.green } Inspect attributes https://developer.apple.com/documentation/objectivec/nsobject/1415656-attributekeys

December 10, 2019 · 1 min · Khoa Pham

How to fix cropped image in UIImageView

Issue #530 Although UIImageView frame is correct, image is still cropped. Watch out for any layer.mask within view

December 6, 2019 · 1 min · Khoa Pham

How to use decoration view in UICollectionView

Issue #529 indexPath https://developer.apple.com/documentation/uikit/uicollectionviewlayoutattributes/1617786-layoutattributesfordecorationvie It is up to you to decide how to use the indexPath parameter to identify a given decoration view. Typically, you use the decorationViewKind parameter to identify the type of the decoration view and the indexPath information to distinguish between different instances of that view. Posts Add separator https://gist.github.com/tomaskraina/1eb291e4717f14ad6e0f8e60ffe9b7d3

December 5, 2019 · 1 min · Khoa Pham

How to test UserDefaults in iOS

Issue #518 let userDefaults = UserDefaults(suiteName: suiteName) userDefaults.removePersistentDomain(forName: suiteName) https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName, and calling the removeObject(forKey:) method on each of its keys. Read more https://www.swiftbysundell.com/articles/the-power-of-userdefaults-in-swift/ http://dscoder.com/defaults.html https://medium.com/swift-india/userdefaults-under-the-hood-457461c8d262

November 25, 2019 · 1 min · Khoa Pham

How to make Swift Package Manager package for multiple platforms

Issue #504 https://twitter.com/NeoNacho/status/1181245484867801088?s=20 There’s no way to have platform specific sources or targets today, so you’ll have to take a different approach. I would recommend wrapping all OS specific files in #if os and just having one target. For tests, you could do something similar, one test target, but conditional tests Every files are in Sources folder, so we can use platform and version checks. For example Omnia is a Swift Package Manager that supports iOS, tvOS, watchOS, macOS and Catalyst....

November 13, 2019 · 1 min · Khoa Pham

How to refresh receipt and restore in app purchase in iOS

Issue #496 Read this Restoring Purchased Products to understand the purposes between the 2. From iOS 7, every app downloaded from the store has a receipt (for downloading/buying the app) at appStoreReceiptURL. When users purchases something via In App Purchase, the content at appStoreReceiptURL is updated with purchases information. Most of the cases, you just need to refresh the receipt (at appStoreReceiptURL) so that you know which transactions users have made....

November 10, 2019 · 2 min · Khoa Pham

How to add monkey test to iOS apps

Issue #484 Use SwiftMonkey which adds random UITests gestures Add to UITests target target 'MyAppUITests' do pod 'R.swift', '~> 5.0' pod 'SwiftMonkey', '~> 2.1.0' end Troubleshooting Failed to determine hittability of Button Failed to determine hittability of Button: Unable to fetch parameterized attribute XC_kAXXCParameterizedAttributeConvertHostedViewPositionFromContext, remote interface does not have this capability. This happens when using SwiftMonkey and somewhere in our code uses isHittable, so best to avoid that by having isolated monkey test only...

November 1, 2019 · 1 min · Khoa Pham

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....

October 29, 2019 · 2 min · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

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 · Khoa Pham

How to find subview recursively in Swift

Issue #460 extension UIView { func findRecursively<T: UIView>(type: T.Type, match: (T) -> Bool) -> T? { for view in subviews { if let subview = view as? T, match(subview) { return subview } else { return view.findRecursively(type: type, match: match) } } return nil } }

October 11, 2019 · 1 min · Khoa Pham