Slide 1

Slide 1 text

What’s new in iOS 9 @adhumi, Trainline Cocoaheads Paris, jan. 2017

Slide 2

Slide 2 text

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

What is already used (or could be)

Slide 8

Slide 8 text

iPad Multitasking / Split screen & slide over Gif animé de changement de size class

Slide 9

Slide 9 text

iPad Multitasking / Split screen & slide over Out of the box ✨ (if you support size classes correctly)

Slide 10

Slide 10 text

iPad Multitasking / Split screen & slide over UIRequireFullScreen Opt-out (info.plist)

Slide 11

Slide 11 text

Search API Add content to spotlight "

Slide 12

Slide 12 text

Search API NSUserActivity For current activity indexation (can be public) var activity = NSUserActivity(activityType: "com.ct.capitainetrain") activity.title = "Paris → Carpentras" activity.userInfo = ["id": "www.trainline.fr/results/paris/carpentras"] activity.isEligibleForSearch = true "

Slide 13

Slide 13 text

Search API " let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData) attributeSet.title = "Private searchable item" let item = CSSearchableItem(uniqueIdentifier: "AE4F-C8C24D", domainIdentifier: "domain", attributeSet: attributeSet) CSSearchableIndex.default().indexSearchableItems([item], completionHandler: nil) CoreSpotlight For massive and/or private, indexation

Slide 14

Slide 14 text

App thinning / Bitcode & App Slicing Archive iTunes Connect App record App Store armv7, arm64 iPhone, iPad screen density

Slide 15

Slide 15 text

App thinning / Bitcode & App Slicing Default on iOS (optional) Mandatory on watchOS and tvOS ⚠ Dependencies need to support Bitcode ~20-50% size gain

Slide 16

Slide 16 text

Keyboard shortcuts

Slide 17

Slide 17 text

Keyboard shortcuts override var keyCommands: [UIKeyCommand]? { return [UIKeyCommand(input: "\r", modifierFlags: .command, action: #selector(onCommandEnter(_:)), discoverabilityTitle: "Validate")] } override var keyCommands: [UIKeyCommand]?

Slide 18

Slide 18 text

3D Touch / Quick Actions

Slide 19

Slide 19 text

3D Touch / Quick Actions let shortcut = UIApplicationShortcutItem(type: "fr.adhumi.app.message", localizedTitle: "Send message") UIApplication.shared.shortcutItems = [shortcut] Dynamic Static Compile time Runtime

Slide 20

Slide 20 text

3D Touch / Peek & Pop func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit vc: UIViewController) { self.navigationController?.pushViewController(vc, animated: true) } override func viewDidLoad() { self.registerForPreviewing(with: self, sourceView: self.view) } func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { return MyController() }

Slide 21

Slide 21 text

What’s really new and can be adopted

Slide 22

Slide 22 text

UIAlertView UIActionSheet ↓ UIAlertController

Slide 23

Slide 23 text

UIAlertController

Slide 24

Slide 24 text

UIAlertController self.present(alert, animated: true, completion: nil) let alert = UIAlertController(title: "Uh oh!", message: "An error occured.", preferredStyle: .alert) let resolve = UIAlertAction(title: "Resolve", style: .destructive) { (action) in // Do stuff } alert.addAction(resolve) let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (action) in // Do stuff } alert.addAction(cancel)

Slide 25

Slide 25 text

UIWebView WKWebView ↓ SFSafariViewController

Slide 26

Slide 26 text

SFSafariViewController

Slide 27

Slide 27 text

SFSafariViewController let url = URL(string: "https://www.trainline.fr") let safari = SFSafariViewController(url: url!) self.navigationController?.pushViewController(safari, animated: true)

Slide 28

Slide 28 text

AddressBook.framework ↓ Contacts.framework

Slide 29

Slide 29 text

Contacts.framework let contacts = CNContactPickerViewController() contacts.delegate = self self.present(contacts, animated: true, completion: nil) func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { print(contact.givenName) print(contact.emailAddresses) } let firstName: String = ABRecordCopyValue(contact, kABPersonFirstNameProperty).takeRetainedValue()

Slide 30

Slide 30 text

App thinning / On Demand Resources Xcode project tag-yellow tag-blue No tag APP

Slide 31

Slide 31 text

App thinning / On Demand Resources let tags: Set = ["tag-yellow, tag-blue"] let request = NSBundleResourceRequest(tags: tags) request.beginAccessingResources { (error) in if let error = error { print(error) } else { print("Resources available") } }

Slide 32

Slide 32 text

NSLayoutConstraint(item: view1, attribute: .centerX, relatedBy: .equal, toItem: view2, attribute: .leading, multiplier: 1, constant: 0) ↓ view1.centerXAnchor.constraint(equalTo: view2.leadingAnchor)

Slide 33

Slide 33 text

Auto Layout New syntax UILayoutGuide ( empty views) Anchors

Slide 34

Slide 34 text

Auto Layout UIStackView

Slide 35

Slide 35 text

Auto Layout

Slide 36

Slide 36 text

Auto Layout let stackView = UIStackView() stackView.axis = .vertical stackView.distribution = .equalSpacing stackView.alignment = .center stackView.spacing = 8 stackView.addArrangedSubview(logo) stackView.addArrangedSubview(title)

Slide 37

Slide 37 text

Split screen Search APIs Bitcode, App Slicing Keyboard shortcuts 3D Touch (peek/pop & quick actions) Auto Layout UIAlertController SFSafariViewController On Demand Resources Contacts.framework

Slide 38

Slide 38 text

Thanks! @adhumi, Trainline trainline.fr/jobs