How to stop implicit animation when title change on UIButton

Issue #345 UIButton with system type has implicit animation for setTitle(_:for:) Use this method to set the title for the button. The title you specify derives its formatting from the button’s associated label object. If you set both a title and an attributed title for the button, the button prefers the use of the attributed title over this one. At a minimum, you should set the value for the normal state....

August 2, 2019 · 1 min · 116 words · Khoa

How to use addSubview in iOS

Issue #344 addSubview can trigger viewDidLayoutSubviews, so be careful to just do layout stuff in viewDidLayoutSubviews This method establishes a strong reference to view and sets its next responder to the receiver, which is its new superview. Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview. When the bounds change for a view controller’€™s view, the view adjusts the positions of its subviews and then the system calls this method....

August 1, 2019 · 1 min · 146 words · Khoa

How to format hour minute from time interval in Swift

Issue #340 Use DateComponentsFormatter https://nshipster.com/formatter/#datecomponentsformatter Results in no padding 0 func format(second: TimeInterval) -> String? { let formatter = DateComponentsFormatter() formatter.unitsStyle = .positional formatter.allowedUnits = [.hour, .minute] formatter.zeroFormattingBehavior = .pad return formatter.string(from: second) } XCTAssertEqual(format(second: 5400 ), "1:30") XCTAssertEqual(format(second: 7200), "2:00") XCTAssertEqual(format(second: 39600 ), "11:00") Use mod func format(minute: Int) -> String { let h = minute / 60 let m = minute % 60 return "\(h.padZero()):\(m.padZero())" } private extension Int { func padZero() -> String { return String(format: "%02d", self) } } XCTAssertEqual(format(minute: 90 ), "01:30") XCTAssertEqual(format(minute: 120), "02:00") XCTAssertEqual(format(minute: 660 ), "11:00")

July 31, 2019 · 1 min · 94 words · Khoa

How to do custom presentation with UIViewPropertyAnimator in iOS

Issue #337 Normally we just present from any UIViewController in any UINavigationController in UITabBarController and it will present over tabbar present(detailViewController, animated: true, completion: nil) If we have animation with UIViewPropertyAnimator, then we can implement UIViewControllerAnimatedTransitioning and interruptibleAnimator(using:) The methods in this protocol let you define an animator object, which creates the animations for transitioning a view controller on or off screen in a fixed amount of time. The animations you create using this protocol must not be interactive....

July 2, 2019 · 2 min · 272 words · Khoa

How to show dropdown in AppKit

Issue #336 Use NSPopUpButton var pullsDown: Bool A Boolean value indicating whether the button displays a pull-down or pop-up menu. func addItem(withTitle: String) Adds an item with the specified title to the end of the menu. Should disable pullsDown if we want to set title automatically and not scale button for title Read more Managing Pop-Up Buttons and Pull-Down Lists

June 29, 2019 · 1 min · 60 words · Khoa

How to scan up to character in Swift

Issue #335 This is useful when we want to get the first meaningful line in a big paragraph let scanner = Scanner(string: text) var result: NSString? = "" scanner.scanUpTo("\n", into: &result) return result as String?

June 29, 2019 · 1 min · 35 words · Khoa

How to use NSSecureCoding in Swift

Issue #334 NSSecureCoding has been around since iOS 6 and has had some API changes in iOS 12 A protocol that enables encoding and decoding in a manner that is robust against object substitution attacks. https://developer.apple.com/documentation/foundation/nscoder/2292924-decodeobject If the coder responds true to requiresSecureCoding, then the coder calls failWithError(_:) in either of the following cases: The class indicated by cls doesn’t implement NSSecureCoding. The unarchived class doesn’t match cls, nor do any of its superclasses....

June 29, 2019 · 2 min · 312 words · Khoa

How to simplify pager interaction with Rx

Issue #333 In a traditional pager with many pages of content, and a bottom navigation with previous and next button. Each page may have different content, and depending on each state, may block the next button. The state of next button should state in real time depending on state in each page content, and when user moves back and forth between pages, the state of next button should be reflected as well....

June 27, 2019 · 2 min · 252 words · Khoa

How to use moveItem in NSCollectionView in AppKit

Issue #332 From moveItem(at:to:) Moves an item from one location to another in the collection view. After rearranging items in your data source object, use this method to synchronize those changes with the collection view. Calling this method lets the collection view know that it must update its internal data structures and possibly update its visual appearance. You can move the item to a different section or to a new location in the same section....

June 27, 2019 · 1 min · 154 words · Khoa

How to show dropdown from NSSegmentedControl in AppKit

Issue #331 From NSSegmentedControl The features of a segmented control include the following: A segment can have an image, text (label), menu, tooltip, and tag. A segmented control can contain images or text, but not both. let languageMenu = NSMenu(title: "") let languages = ["Swift", "Javascript"] languages.forEach { let item = NSMenuItem(title: $0, action: #selector(handleSelectLanguage(_:)), keyEquivalent: "") item.target = self item.isEnabled = true languageMenu.addItem(item) } let themeMenu = NSMenu(title: "") let themes = ["one dark", "one light"] themes....

June 27, 2019 · 1 min · 118 words · Khoa

How to make scrollable NSTextView in AppKit

Issue #330 When adding NSTextView in xib, we see it is embedded under NSClipView. But if we try to use NSClipView to replicate what’s in the xib, it does not scroll. To make it work, we can follow Putting an NSTextView Object in an NSScrollView and How to make scrollable vertical NSStackView to make our ScrollableInput For easy Auto Layout, we use Anchors for UIScrollView. Things worth mentioned for vertical scrolling...

June 26, 2019 · 1 min · 202 words · Khoa

How to handle keyboard for UITextField in scrolling UIStackView in iOS

Issue #329 Firstly, to make UIStackView scrollable, embed it inside UIScrollView. Read How to embed UIStackView inside UIScrollView in iOS It’s best to listen to keyboardWillChangeFrameNotification as it contains frame changes for Keyboard in different situation like custom keyboard, languages. Posted immediately prior to a change in the keyboard’s frame. class KeyboardHandler { let scrollView: UIScrollView let stackView: UIStackView var observer: AnyObject? var keyboardHeightConstraint: NSLayoutConstraint! struct Info { let frame: CGRect let duration: Double let animationOptions: UIView....

June 26, 2019 · 4 min · 747 words · Khoa

How to make simple form validator in Swift

Issue #328 Sometimes we want to validate forms with many fields, for example name, phone, email, and with different rules. If validation fails, we show error message. We can make simple Validator and Rule class Validator { func validate(text: String, with rules: [Rule]) -> String? { return rules.compactMap({ $0.check(text) }).first } func validate(input: InputView, with rules: [Rule]) { guard let message = validate(text: input.textField.text ?? "", with: rules) else { input....

June 25, 2019 · 2 min · 305 words · Khoa

How to organise test files

Issue #327 In terms of tests, we usually have files for unit test, UI test, integeration test and mock. Out of sight, out of mind. Unit tests are for checking specific functions and classes, it’s more convenient to browse them side by side with source file. For example in Javascript, Kotlin and Swift index.js index.test.js index.mock.js LocationManager.kt LocationManager.mock.kt LocationManager.test.kt BasketHandler.swift BasketHandler.mock.swift BasketHandler.test.swift Integration tests check features or sub features, and may cover many source files, it’s better to place them in feature folders...

June 25, 2019 · 1 min · 105 words · Khoa

How to deal with weak in closure in Swift

Issue #326 Traditionally, from Swift 4.2 we need guard let self addButton.didTouch = { [weak self] in guard let self = self, let product = self.purchasedProduct() else { return self.delegate?.productViewController(self, didAdd: product) } This is cumbersome, we can invent a higher order function to zip and unwrap the optionals func with<A, B>(_ op1: A?, _ op2: B?, _ closure: (A, B) -> Void) { if let value1 = op1, let value2 = op2 { closure(value1, value2) } } addButton....

June 25, 2019 · 1 min · 92 words · Khoa

How to make material UITextField with floating label in iOS

Issue #325 Use UILabel as placeholder and move it When label is moved up, scale it down 80%. It means it has 10% padding on the left and right when shrinked, so offsetX for translation is 10% Translation transform should happen before scale Ideally we can animate font and color change using CATextLayer, but with UILabel we can use UIView.transition final class MaterialInputView: UIView { lazy var label: UILabel = { return UILabel() }() lazy var textField: UITextField = { let textField = UITextField() textField....

June 24, 2019 · 2 min · 335 words · Khoa

How to embed UIStackView inside UIScrollView in iOS

Issue #324 view.addSubview(scrollView) scrollView.addSubview(stackView) NSLayoutConstraint.on([ scrollView.pinEdges(view: view), stackView.pinEdges(view: scrollView) ]) NSLayoutConstraint.on([ stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0) ]) Updated at 2020-09-07 14:28:15

June 24, 2019 · 1 min · 20 words · Khoa

How to animate NSCollectionView changes

Issue #323 Use proxy animator() let indexPath = IndexPath(item: index, section: 0) collectionView.animator().deleteItems(at: Set(arrayLiteral: indexPath)) let indexPath = IndexPath(item: 0, section: 0) collectionView.animator().insertItems(at: Set(arrayLiteral: indexPath))

June 23, 2019 · 1 min · 25 words · Khoa

How to handle right click in AppKit

Issue #322 lazy var gr = NSClickGestureRecognizer(target: self, action: #selector(onPress(_:))) gr.buttonMask = 0x2 gr.numberOfClicksRequired = 1 view.addGestureRecognizer(gr)

June 23, 2019 · 1 min · 17 words · Khoa

How to show context menu in NSCollectionView

Issue #321 Detect locationInWindow in NSEvent class ClickedCollectionView: NSCollectionView { var clickedIndex: Int? override func menu(for event: NSEvent) -> NSMenu? { clickedIndex = nil let point = convert(event.locationInWindow, from: nil) for index in 0..<numberOfItems(inSection: 0) { let frame = frameForItem(at: index) if NSMouseInRect(point, frame, isFlipped) { clickedIndex = index break } } return super.menu(for: event) } } let menu = NSMenu() menu.addItem(NSMenuItem(title: "Delete", action: #selector(didSelectDelete(_:)), keyEquivalent: "")) collectionView.menu = menu @objc func didSelectDelete(_ item: NSMenuItem) { guard let index = collectionView....

June 23, 2019 · 1 min · 138 words · Khoa