How to test push notifications in simulator and production iOS apps

Issue #682 After has recently reminded about his updating APNs provider API which makes me realised a lot has changed about push notifications, both in terms of client and provider approach. The HTTP/2-based Apple Push Notification service (APNs) provider API lets you take advantage of great features, such as authentication with a JSON Web Token, improved error messaging, and per-notification feedback. If you send push notifications with the legacy binary protocol, we strongly recommend upgrading to the APNs provider API....

October 11, 2020 · 12 min · 2474 words · Khoa

How to draw arc corner using Bezier Path

Issue #673 To draw rounded 2 corners at top left and top right, let’s start from bottom left let path = UIBezierPath() // bottom left path.move(to: CGPoint(x: 0, y: bounds.height)) // top left corner path.addArc(withCenter: CGPoint(x: radius, y: radius), radius: radius, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3 / 2, clockwise: true) // top right corner path.addArc(withCenter: CGPoint(x: bounds.width - radius, y: radius), radius: radius, startAngle: CGFloat.pi * 3 / 2, endAngle: 0, clockwise: true) // bottom right path....

September 15, 2020 · 1 min · 86 words · Khoa

How to make dynamic font size for UIButton

Issue #671 Use adjustsFontForContentSizeCategory A Boolean that indicates whether the object automatically updates its font when the device’s content size category changes. If you set this property to YES, the element adjusts for a new content size category on a UIContentSizeCategoryDidChangeNotification. button.titleLabel?.adjustsFontForContentSizeCategory = true button.backgroundColor = UIColor.green button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title1) label.adjustsFontForContentSizeCategory = true label.backgroundColor = UIColor.yellow label.font = UIFont.preferredFont(forTextStyle: .title1) However it seems view (UIButton or UILabel) size is the same, just the inner text increases in size....

August 14, 2020 · 1 min · 95 words · Khoa

How to test for view disappear in navigation controller

Issue #670 To test for viewWillDisappear during UINavigationController popViewController in unit test, we need to simulate UIWindow so view appearance works. final class PopTests: XCTestCase { func testPop() { let window = UIWindow(frame: UIScreen.main.bounds) let navigationController = UINavigationController() window.rootViewController = navigationController let viewController = DetailViewController() navigationController.viewControllers = [ UIViewController(), viewController ] window.makeKeyAndVisible() let expectation = XCTestExpectation() navigationController.popViewController(animated: false) DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { XCTAssertTrue(viewController.wasDismissed) expectation.fulfill() } wait(for: [expectation], timeout: 1) } } class DetailViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super....

August 6, 2020 · 1 min · 96 words · Khoa

How to set text color for UIDatePicker

Issue #660 Apply tintColor does not seem to have effect. datePicker.setValue(UIColor.label, forKeyPath: "textColor") datePicker.setValue(false, forKey: "highlightsToday")

June 10, 2020 · 1 min · 16 words · Khoa

How to use background in iOS

Issue #631 beginBackgroundTask https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/extending_your_app_s_background_execution_time When your app moves to the background, the system calls your app delegate’s applicationDidEnterBackground(_:) method. That method has five seconds to perform any tasks and return. Shortly after that method returns, the system puts your app into the suspended state. For most apps, five seconds is enough to perform any crucial tasks, but if you need more time, you can ask UIKit to extend your app’s runtime....

March 25, 2020 · 2 min · 297 words · Khoa

How to mask with UILabel

Issue #603 Need to set correct frame for mask layer or UILabel, as it is relative to the coordinate of the view to be masked let aView = UIView(frame: .init(x: 100, y: 110, width: 200, height: 100)) let textLayer = CATextLayer() textLayer.foregroundColor = UIColor.white.cgColor textLayer.string = "Hello world" textLayer.font = UIFont.preferredFont(forTextStyle: .largeTitle) textLayer.frame = aView.bounds aView.layer.mask = textLayer Use sizeToFit to ensure frame for UILabel let label = UILabel() label.frame.origin = CGPoint(x: 80, y: 80) label....

February 13, 2020 · 1 min · 205 words · Khoa

How to sync multiple CAAnimation

Issue #600 Use same CACurrentMediaTime final class AnimationSyncer { static let now = CACurrentMediaTime() func makeAnimation() -> CABasicAnimation { let animation = CABasicAnimation(keyPath: "opacity") animation.fillMode = .forwards animation.fromValue = 0 animation.toValue = 1 animation.repeatCount = .infinity animation.duration = 2 animation.beginTime = Self.now animation.autoreverses = true animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) return animation } }

February 11, 2020 · 1 min · 53 words · Khoa

How to build SwiftUI style UICollectionView data source in Swift

Issue #598 It’s hard to see any iOS app which don’t use UITableView or UICollectionView, as they are the basic and important foundation to represent data. UICollectionView is very basic to use, yet a bit tedious for common use cases, but if we abstract over it, then it becomes super hard to customize. Every app is unique, and any attempt to wrap around UICollectionView will fail horribly. A sensable approach for a good abstraction is to make it super easy for normal cases, and easy to customize for advanced scenarios....

February 9, 2020 · 4 min · 832 words · Khoa

How to weak link Combine in macOS 10.14 and iOS 12

Issue #593 #if canImport(Combine) is not enough, need to specify in Other Linker Flags OTHER_LDFLAGS = -weak_framework Combine Read more https://stackoverflow.com/questions/57168931/optional-linking-for-swift-combine-framework-in-xcode-11

February 2, 2020 · 1 min · 21 words · Khoa

How to test drag and drop in UITests

Issue #583 In UITests, we can use press from XCUIElement to test drag and drop let fromCat = app.buttons["cat1"].firstMatch let toCat = app.buttons["cat2"] let fromCoordinate = fromCat.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0)) let toCoordinate = toCat.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: -0.5)) fromCoordinate.press(forDuration: 1, thenDragTo: toCoordinate) and then take screenshot let screenshot = XCUIScreen.main.screenshot() let attachment = XCTAttachment(screenshot: screenshot) attachment.lifetime = .keepAlways attachment.name = name add(attachment) Screenshot capturing happens after the action, so it may be too late....

January 23, 2020 · 1 min · 167 words · Khoa

How to set corner radius in iOS

Issue #582 Use View Debugging Run on device, Xcode -> Debug -> View debugging -> Rendering -> Color blended layer On Simulator -> Debug -> Color Blended Layer Corner radius https://twitter.com/timoliverau/status/1135999854176395264 Okay. Talked to a Core Animation engineer again: cornerRadius was deliberately improved in Metal so it could be used everywhere. Using a bitmap is WAY heavier in terms of memory and performance. CALayer maskLayer is still heavy. https://developer.apple.com/documentation/quartzcore/calayer/1410818-cornerradius Setting the radius to a value greater than 0....

January 22, 2020 · 4 min · 790 words · Khoa

How to work with SceneDelegate in iOS 12

Issue #580 Events open url https://stackoverflow.com/questions/58624786/method-applicationopenurloptions-is-not-called Implement scene(_:openURLContexts:) in your scene delegate. If the URL launches your app, you will get scene(_:willConnectTo:options:) instead and it’s in the options. life cycle https://stackoverflow.com/questions/56508764/app-delegate-methods-arent-being-called-in-ios-13 Here’s how it works: If you have an “Application Scene Manifest” in your Info.plist and your app delegate has a configurationForConnectingSceneSession method, the UIApplication won’t send background and foreground lifecycle messages to your app delegate. That means the code in these methods won’t run:...

January 20, 2020 · 2 min · 300 words · Khoa

How to make rotation in same direction in iOS

Issue #571 From CGFloat.pi / 2 to -CGFloat.pi / 2 + epsilon

January 6, 2020 · 1 min · 12 words · Khoa

How to get updated safeAreaInsets in iOS

Issue #570 Use viewSafeArea @available(iOS 11.0, *) override func viewSafeAreaInsetsDidChange() { super.viewSafeAreaInsetsDidChange() self.collectionView.reloadData() } Use https://developer.apple.com/documentation/uikit/uiview/2891102-safearealayoutguide view.safeAreaLayoutGuide.layoutFrame https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets For the view controller’s root view, the insets account for the status bar, other visible bars, and any additional insets that you specified using the additionalSafeAreaInsets property of your view controller. For other views in the view hierarchy, the insets reflect only the portion of the view that is covered. For example, if a view is entirely within the safe area of its superview, the edge insets in this property are 0....

January 6, 2020 · 2 min · 333 words · Khoa

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 · 179 words · Khoa

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 · 963 words · Khoa

How to use safeAreaInsets in iOS

Issue #561 Read more https://medium.com/rosberryapps/ios-safe-area-ca10e919526f https://blog.smartnsoft.com/layout-guide-margins-insets-and-safe-area-demystified-on-ios-10-11-d6e7246d7cb8 https://www.matrixprojects.net/p/safe-area-insets/ https://stackoverflow.com/questions/37796884/on-ios-what-are-the-differences-between-margins-edge-insets-content-insets-a/47614397

December 30, 2019 · 1 min · 8 words · Khoa

Why is didSelectItem not called in UICollectionView

Issue #550 Check shouldHighlightItem -> shouldSelectItem -> didSelectItem Gesture recognizer isUserInteractionEnabled

December 20, 2019 · 1 min · 11 words · Khoa

How to use deep link and universal link in iOS

Issue #548 https://stackoverflow.com/questions/35522618/universal-links-on-ios-vs-deep-links-url-schemes

December 18, 2019 · 1 min · 3 words · Khoa