How to show location in Apple Maps and Google Maps app in iOS

Issue #309 Apple Maps let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: nil) let mapItem = MKMapItem(placemark: placemark) mapItem.name = shop.name mapItem.openInMaps(launchOptions: [:]) Google Maps https://developers.google.com/maps/documentation/urls/ios-urlscheme Use q to show pin Since iOS 9, we need to declare LSApplicationQueriesSchemes <key>LSApplicationQueriesSchemes</key> <array> <string>comgooglemaps</string> </array> var string = "comgooglemaps://" string += "?q=Food" string += "&center=\(coordinate.latitude),\(coordinate.longitude)" string += "&zoom=15" let googleUrl = URL(string: string)! if UIApplication.shared.canOpenURL(URL(string: "comgooglemaps://")!) { UIApplication.shared.open(googleUrl) }

June 13, 2019 · 1 min · 65 words · Khoa

How to format distance in iOS

Issue #307 import MapKit let formatter = MKDistanceFormatter() formatter.unitStyle = .abbreviated formatter.units = .metric distanceLabel.text = formatter.string(fromDistance: distance) // 700m, 1.7km

June 13, 2019 · 1 min · 21 words · Khoa

How to test drive view in iOS

Issue #303 Instead of setting up custom framework and Playground, we can just display that specific view as root view controller window.rootViewController = makeTestPlayground() func makeTestPlayground() -> UIViewController { let content = UserCell() content.nameLabel.text = "Thor" content.streetLabel.text = "Asgard" content.weaponLabel.text = "Hammer" let viewController = UIViewController() viewController.view.backgroundColor = .white viewController.view.addSubview(content) NSLayoutConstraint.on([ content.centerXAnchor.constraint(equalTo: viewController.view.centerXAnchor), content.centerYAnchor.constraint(equalTo: viewController.view.centerYAnchor), content.widthAnchor.constraint(equalTo: viewController.view.widthAnchor, multiplier0.9), content.heightAnchor.constraint(equalToConstant: 200) ] return viewController }

June 12, 2019 · 1 min · 64 words · Khoa

How to make carousel layout for UICollectionView in iOS

Issue #302 Based on AnimatedCollectionViewLayout final class CarouselLayout: UICollectionViewFlowLayout { override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil } guard let collectionView = collectionView else { return nil } return attributes.map({ transform(collectionView: collectionView, attribute: $0) }) } override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } private func transform(collectionView: UICollectionView, attribute: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { let a = attribute let width = collectionView....

June 12, 2019 · 3 min · 635 words · Khoa

How to make simple pan to dismiss view in iOS

Issue #301 Make it more composable using UIViewController subclass and ThroughView to pass hit events to underlying views. class PanViewController: UIViewController { var animator = UIViewPropertyAnimator(duration: 0, curve: .easeOut) lazy var panGR = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_: ))) let slideView = UIView() let gripView = UIView() var options: Options = Options() var didHide: (() -> Void)? let pullDownVelocity: CGFloat = 70 class Options { var contentView: UIView = UIView() var percentHeight: CGFloat = 0....

June 12, 2019 · 2 min · 306 words · Khoa

How to add indicator under tab bar buttons in iOS

Issue #288 selectionIndicatorImage https://developer.apple.com/documentation/uikit/uitabbar/1623456-selectionindicatorimage Should design image with enough height, transparent background and indicator at the bottom Use this property to specify a custom selection image. Your image is rendered on top of the tab bar but behind the contents of the tab bar item itself. The default value of this property is nil, which causes the tab bar to apply a default highlight to the selected item Custom UITabBar or UITabBarController Hide existing tabBar tabBar....

May 27, 2019 · 2 min · 374 words · Khoa

How to fix wrong status bar orientation in iOS

Issue #280 Original post https://medium.com/fantageek/how-to-fix-wrong-status-bar-orientation-in-ios-f044f840b9ed When I first started iOS, it was iOS 8 at that time, I had a bug that took my nearly a day to figure out. The issue was that the status bar always orients to device orientation despite I already locked my main ViewController to portrait. This was why I started notes project on GitHub detailing what issues I ‘ve been facing. ViewController is locked to portrait but the status bar rotates when device rotates · Issue #2 ·… *PROBLEM The rootViewController is locked to portrait....

May 23, 2019 · 3 min · 600 words · Khoa

Learn iOS best practices by building a simple recipes app

Issue #258 I started iOS development when iOS 7 had been announced. And I have learned a bit, through working, advice from colleagues and the iOS community. In this article, I’d like to share a lot of good practices by taking the example of a simple recipes app. The source code is at GitHub Recipes. The app is a traditional master detail application that showcases a list of recipes together with their detailed information....

May 23, 2019 · 28 min · 5880 words · Khoa

How to move tab bar icons down in iOS

Issue #250 UITabBarItem subclasses from UIBarItem which has imageInsets. We need both top and bottom to avoid shrinking viewController1.tabBarItem.imageInsets = UIEdgeInsets(top: 10, left: 0, bottom: -10, right: 0)

May 21, 2019 · 1 min · 28 words · Khoa

How to test LaunchScreen in iOS

Issue #249 Making splash screen with LaunchScreen.storyboard is now the default way to do in iOS. Testing it with UITests is a bit tricky as this screen is showed the system, and if we test that, we are just testing the system. What we should test is the content we put in the LaunchScreen storyboard. Is it showing correctly on different screen sizes? Is it missing any texts or images?...

May 21, 2019 · 1 min · 134 words · Khoa

How to enable black mode in Google Maps in iOS

Issue #246 Use GMSMapStyle https://developers.google.com/maps/documentation/android-sdk/styling Export styling json from https://mapstyle.withgoogle.com/ let mapStyleUrl = Bundle.main.url(forResource: "mapStyle", withExtension: "json")! mapView.mapStyle = try? GMSMapStyle(contentsOfFileURL: mapStyleUrl) To change overall color, search for mostly "elementType": "geometry" and "featureType": "water" { "elementType": "geometry", "stylers": [ { "color": "#424242" } ] } { "featureType": "water", "elementType": "geometry", "stylers": [ { "color": "#2E2E2E" } ] }

May 20, 2019 · 1 min · 58 words · Khoa

Favorite WWDC 2018 sessions

Issue #245 Original post https://medium.com/fantageek/my-favourite-wwdc-2018-sessions-363d3fc9c9d5 Favourite WWDC 2018 sessions This year I failed the lottery ticket to WWDC, and I also missed the keynote live stream because I was sailing on the Christian Radich outside Oslo fjord that day. Luckily all the videos are available on Apple Developer site very shortly, and we can watch them now on Chrome or the unofficial WWDC app on macOS. I recommend the WWDC macOS app as it allows to mark favourites and filter, also offers the ability to adjust play speed to 1....

May 19, 2019 · 9 min · 1767 words · Khoa

How to fit UIBezierPath in frame in iOS

Issue #232 From https://github.com/xhamr/paintcode-path-scale with some updates extension CGRect { var center: CGPoint { return CGPoint( x: self.size.width/2.0,y: self.size.height/2.0) } } extension CGPoint { func vector(to p1:CGPoint) -> CGVector { return CGVector(dx: p1.x - x, dy: p1.y - y) } } extension UIBezierPath { func moveCenter(to:CGPoint) -> Self { let bounds = self.cgPath.boundingBox let center = bounds.center let zeroedTo = CGPoint(x: to.x - bounds.origin.x, y: to.y - bounds.origin.y) let vector = center....

May 14, 2019 · 2 min · 223 words · Khoa

How to use CAReplicatorLayer to make activity indicator in iOS

Issue #230 CAReplicatorLayer is a layer that creates a specified number of sublayer copies with varying geometric, temporal, and color transformations Here we use instanceTransform which applies transformation matrix around the center of the replicator layer Below is how we use replicatorLayer to replicate lots of line and rotate them around the center. let replicatorLayer = CAReplicatorLayer() let animation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity)) let line = CALayer() let lineCount: Int = 12 let duration: TimeInterval = 1....

May 13, 2019 · 1 min · 199 words · Khoa

How to do rotation for CALayer in iOS

Issue #229 Use keypath let animation = CASpringAnimation(keyPath: #keyPath(CALayer.transform)) animation.fromValue = 0 animation.valueFunction = CAValueFunction(name: CAValueFunctionName.rotateZ) animation.timingFunction = CAMediaTimingFunction(name: .easeIn) animation.toValue = CGFloat.pi / 4 Avoid setting frame many times Otherwise, frame is the box that covers the rotation transform, and backgroundColor now fills that huge box override func layoutSubviews() { super.layoutSubviews() guard line.frame.width <= 0 else { return } line.backgroundColor = UIColor.red.cgColor line.cornerRadius = 3 line.frame.size = CGSize(width: bounds.width*0.6, height: 6) line....

May 13, 2019 · 1 min · 86 words · Khoa

How to not use isRemovedOnCompletion for CAAnimation in iOS

Issue #228 CAAnimation is about presentation layer, after animation completes, the view snaps back to its original state. If we want to keep the state after animation, then the wrong way is to use CAMediaTimingFillMode.forward and isRemovedOnCompletion Animation never ends forwards https://developer.apple.com/documentation/quartzcore/camediatimingfillmode/1427658-forwards The receiver remains visible in its final state when the animation is completed. isRemovedOnCompletion https://developer.apple.com/documentation/quartzcore/caanimation/1412458-isremovedoncompletion When true, the animation is removed from the target layer’s animations once its active duration has passed....

May 13, 2019 · 1 min · 145 words · Khoa

How to make simple search box in iOS

Issue #227 final class SearchBox: UIView { lazy var textField: UITextField = { let textField = UITextField() let imageView = UIImageView(image: R.image.search()!) imageView.frame.size = CGSize(width: 20 + 8, height: 20) imageView.contentMode = .scaleAspectFit textField.leftView = imageView textField.leftViewMode = .always return textField }() lazy var filterButton: UIButton = { let button = UIButton(type: .custom) button.setImage(R.image.filter()!, for: .normal) button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) return button }() lazy var backView: UIView = { let view = UIView() view....

May 7, 2019 · 1 min · 207 words · Khoa

How to capture video in iOS simulator

Issue #226 Take screenshot xcrun simctl io booted screenshot image.png Record video xcrun simctl io booted recordVideo video.mp4

May 7, 2019 · 1 min · 18 words · Khoa

How to use custom fonts in iOS

Issue #225 <key>UIAppFonts</key> <array> <string>OpenSans-Bold.ttf</string> <string>OpenSans-BoldItalic.ttf</string> <string>OpenSans-ExtraBold.ttf</string> <string>OpenSans-ExtraBoldItalic.ttf</string> <string>OpenSans-Italic.ttf</string> <string>OpenSans-Light.ttf</string> <string>OpenSans-LightItalic.ttf</string> <string>OpenSans-Regular.ttf</string> <string>OpenSans-SemiBold.ttf</string> <string>OpenSans-SemiBoldItalic.ttf</string> </array> Read Adding a Custom Font to Your App The name of the font isn’t always obvious, and rarely matches the font file name. A quick way to find the font name is to get the list of fonts available to your app, which you can do with the following code: for family in UIFont.familyNames.sorted() { let names = UIFont....

May 7, 2019 · 1 min · 81 words · Khoa

How to create UITabBarController programmatically in iOS

Issue #224 let tabBarController = UITabBarController() let navigationController1 = UINavigationController(rootViewController: viewController1) let navigationController2 = UINavigationController(rootViewController: viewController2) let navigationController3 = UINavigationController(rootViewController: viewController3) navigationController2.isNavigationBarHidden = true navigationController1.tabBarItem.image = R.image.profile() navigationController2.tabBarItem.image = R.image.books() navigationController3.tabBarItem.image = R.image.settings() tabBarController.tabBar.tintColor = .yellow tabBarController.viewControllers = [navigationController1, navigationController2, navigationController3] Use tintColor instead of the deprecated selectedImageTintColor to indicate selected item color. For icon size, check Tab Bar Icon Size, usually 50x50 for 2x and 75x75 for 3x In portrait orientation, tab bar icons appear above tab titles....

May 7, 2019 · 1 min · 115 words · Khoa