How to make custom controller for View in iOS

Issue #318 I do UI in code, and usually separate between View and ViewController. class ProfileView: UIView {} class ProfileViewController: UIViewController { override func loadView() { self.view = ProfileView() } } But in places where using UIViewController and manage their view controller containment hierarchy is not desired, then we can roll out a normal object to act as the controller. class ProfileController { let profileView: ProfileView init(profileView: ProfileView) { self.profileView = profileView } func update(profile: Profile) { profileView....

June 19, 2019 · 1 min · 103 words · Khoa

A bit about Design

Issue #317 UI Why Your App Looks Better in Sketch 8 Tips for Dark Theme Design UX Duolingo User Retention Design Details 30 Things We Often Forget When Designing Mobile Apps Case study club Showcase https://saaspages.xyz/ Resources https://shape.so/ https://icons8.com/ https://icons8.com/animated-icons https://icons8.com/vector-creator https://feathericons.com/ https://iconstore.co/ https://streamlineicons.com/

June 18, 2019 · 1 min · 44 words · Khoa

Links for Design

Issue #317 UI Why Your App Looks Better in Sketch 8 Tips for Dark Theme Design UX Duolingo User Retention Design Details 30 Things We Often Forget When Designing Mobile Apps Case study club Showcase https://saaspages.xyz/ Resources https://shape.so/ https://icons8.com/ https://icons8.com/animated-icons https://icons8.com/vector-creator https://feathericons.com/ https://iconstore.co/ https://streamlineicons.com/ https://illlustrations.co/

June 18, 2019 · 1 min · 45 words · Khoa

Understanding device and OS share for iOS and Android

Issue #316 Browsers and devices used in 2018 AppStore measurement

June 18, 2019 · 1 min · 10 words · Khoa

How to make UIPanGestureRecognizer work with horizontal swipe in UICollectionView

Issue #315 extension PanCollectionViewController: UIGestureRecognizerDelegate { func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { let velocity = panGR.velocity(in: panGR.view) return abs(velocity.y) > abs(velocity.x) } }

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

How to use media query in CSS

Issue #314 <meta name="viewport" content="width=device-width, initial-scale=1.0"> @media only screen and (max-width: 600px) { div.container { margin: 0 auto; width: 70%; margin-top: 60%; } } body { background-image: url("../images/wallpaper.png"); background-position: top right; background-attachment: fixed; background-size: cover; }

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

How to use new APIs in iOS

Issue #313 iOS 10 ➕UserNotifications Push user-facing notifications to the user’s device from a server, or generate them locally from your app. ➕UIViewPropertyAnimator A class that animates changes to views and allows the dynamic modification of those animations. ➕NSPersistentContainer A container that encapsulates the Core Data stack in your app. ➕UIFeedbackGenerator The abstract superclass for all feedback generators. iOS 10.3 ➕SKStoreReviewController An object that controls the process of requesting App Store ratings and reviews from users....

June 17, 2019 · 2 min · 241 words · Khoa

Links for WWDC

Issue #313 iOS 10 ➕UserNotifications Push user-facing notifications to the user’s device from a server, or generate them locally from your app. ➕UIViewPropertyAnimator A class that animates changes to views and allows the dynamic modification of those animations. ➕NSPersistentContainer A container that encapsulates the Core Data stack in your app. ➕UIFeedbackGenerator The abstract superclass for all feedback generators. iOS 10.3 ➕SKStoreReviewController An object that controls the process of requesting App Store ratings and reviews from users....

June 17, 2019 · 2 min · 241 words · Khoa

What is new in iOS

Issue #313 iOS 10 ➕UserNotifications Push user-facing notifications to the user’s device from a server, or generate them locally from your app. ➕UIViewPropertyAnimator A class that animates changes to views and allows the dynamic modification of those animations. ➕NSPersistentContainer A container that encapsulates the Core Data stack in your app. ➕UIFeedbackGenerator The abstract superclass for all feedback generators. iOS 10.3 ➕SKStoreReviewController An object that controls the process of requesting App Store ratings and reviews from users....

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

What's new in iOS

Issue #313 iOS 10 ➕UserNotifications Push user-facing notifications to the user’s device from a server, or generate them locally from your app. ➕UIViewPropertyAnimator A class that animates changes to views and allows the dynamic modification of those animations. ➕NSPersistentContainer A container that encapsulates the Core Data stack in your app. ➕UIFeedbackGenerator The abstract superclass for all feedback generators. iOS 10.3 ➕SKStoreReviewController An object that controls the process of requesting App Store ratings and reviews from users....

June 17, 2019 · 2 min · 237 words · Khoa

How to avoid crash when closing NSWindow for agent macOS app

Issue #312 class ClosableWindow: NSWindow { override func close() { self.orderOut(NSApp) } } let window = ClosableWindow( contentRect: rect, styleMask: [.titled, .closable], backing: .buffered, defer: false } window.makeKeyAndOrderFront(NSApp) The reason is that window is released upon closed if it is not owned by NSWindowController, or we can use releasedWhenClosed The value of this property is YES if the window is automatically released after being closed; NO if it’s simply removed from the screen....

June 16, 2019 · 1 min · 116 words · Khoa

How to get cell at center during scroll in UICollectionView

Issue #311 See Omnia https://github.com/onmyway133/Omnia/blob/master/Sources/iOS/UICollectionView.swift#L30 extension HorizontalUsersViewController: UIScrollViewDelegate { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let point = view.convert(collectionView.center, to: collectionView) guard let indexPath = collectionView.indexPathForItem(at: point), indexPath.item < users.count else { return } let user = users[indexPath.item] delegate?.didScrollTo(user) } }

June 14, 2019 · 1 min · 40 words · Khoa

How to downsample image in iOS

Issue #310 https://www.swiftjectivec.com/optimizing-images/ https://nshipster.com/image-resizing/

June 14, 2019 · 1 min · 4 words · Khoa

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 make convenient touch handler for UIButton in iOS

Issue #308 If you don’t want to use https://github.com/onmyway133/EasyClosure yet, it’s easy to roll out a closure based UIButton. The cool thing about closure is it captures variables final class ClosureButton: UIButton { var didTouch: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame) addTarget(self, action: #selector(buttonTouched(_:)), for: .touchUpInside) } required init?(coder aDecoder: NSCoder) { fatalError() } @objc private func buttonTouched(_: UIButton) { didTouch?() } } Then in cellForItem func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell: UserCell = collectionView....

June 13, 2019 · 1 min · 157 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 mock grpc model in Swift

Issue #306 let json: [String: Any] = [ "id": "123", "name": "Thor", "isInMarvel": true ] let data = try JSONSerialization.data(withJSONObject: json, options: []) let string = String(data: data, encoding: .utf8)! return try Hero(jsonString: string) If we use withValue from How to simplify struct mutating in Swift then we can mock easily extension Hero { static func mock() -> Hero { return withValue(Hero()) { $0.id = "123" $0.name = "Thor" $0.isInMarvel = true } } }

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

Favorite WWDC 2019 sessions

Issue #305 This year I’m lucky enough to get the ticket to WWDC and I couldn’t be more satisfied. 5 conference days full of awesomeness, talks, labs and networking, all make WWDC special and memorial conference for every attendee. As predicted by many, Marzipan (now officially called Project Catalyst) a technology that could allow iOS apps to be ported to macOS, would be the main topic for this year. But WWDC went more spectacular than that, with dark mode on iOS, independent watchOS apps, and SwiftUI being the star of the show....

June 12, 2019 · 8 min · 1606 words · Khoa

Support IP handover in rtpproxy for VoIP applications

Issue #304 If you do VoIP applications, especially with open sources like pjsip, you may encounter kamalio and rtpproxy to serve SIP requests. Due to limitation of NAT traversals, rtpproxy is needed to work around NAT. All SIP handshake requests go through a proxy server, but rtpproxy can also relay voice, video or any RTP stream of data. When I played with rtpproxy, it was before version 2.0 and I need to handle IP handover....

June 12, 2019 · 5 min · 974 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