sobota, 9 stycznia 2016

iOS 8 & 9

Po Swifcie rzutem na taśmę przejrzałem z grubsza zmiany w ostatnich dwóch wersjach iOS 8 i 9. Generalnie zaskoczenia nie ma, a większość rzeczy jest jakby już skądś znanych.  Skąd?  Odnajduję kilka analogii, czasami wprost do tego, co można było zaobserwować w Windows 8.x czy 10. Ale teraz już pokolei pozwolę skomentować sobie, co najbardziej istotne.

  • aplikacje uniwersalne - jeden widok z warunkami na różne ekrany (Windows 10 też wprowadził taką możliwość, powiedziałbym, że warunki ma zrealizowane bardziej uniwersalnie)
  • dynamics frameworks - dzielone biblioteki między aplikacje (dopiero w wersji 8?)
  • view debugging - jak Live DOM w Visual Studio dla XAML (trzeba przyznać, że Apple poszło dalej i wizualizuje także warstwowo w przestrzeni)
  • iOS extensions - no proszę, mi się jednoznacznie kojarzą z kontraktami/rozszerzeniami Windows od 8.x, np. sharowanie, file picker  (komunikacja za pomocą linka też jest w aplikacjach Windows Store)
  • UIStackView - nareszcie coś na kształt w miarę normalnego StackPanel z XAML, aczkolwiek trochę urozmaicony
  • UILayoutGuide - pewne uproszczenia mocno niezjadliwego definiowania warunków layoutu w kodzie, aczkolwiek w dalszym ciągu nie widzę tutaj odpowiedniej prostoty
  • Multitasking - wyświetlanie kilku aplikacji na jednym ekranie, snapowanie?  znamy to z Windows 8!, aczkolwiek Apple urozmaicił to trybem over oraz pokazywaniem ramki video
  • “pliki nagłówkowe” dla Swift - widok podsumowujący “interfejs” klasy C# mamy od dawna w VS
  • App Thinning - pobieranie tylko potrzebnych zasobów dla danego urządzenia, kompilacja w Store, znamy to od Windows/Windows Phone 8.1
  • API do kontaktów - nareszcie jakieś sensowne API, mocno nawiązujące IMHO do hm… API z Windows
  • Search API - wyszukiwanie frazy powiązanej z aplikacją hm… również jakoś nie zaskakuje

 

iOS 8

w skrócie

  • uniwersalne aplikacje
  • więcej możliwości interakcji z innymi aplikacjami
  • ułatwienia w autentykacji
  • ułatwienia w płatnościach mobilnych (Apple Pay)
  • wsparcie dla Swift

XCode 6

wsparcie dla Swift prawie takie samo jak dla Objective-C (m.in brak refaktoringu)

testy - m.in Swift i asynchroniczność

iOS 8 Dynamic Frameworks

  • dzielone między wiele aplikacji
  • wcześniej tylko dzielenie źródeł lub statyczne biblioteki
  • szablon: iOS –> Framework & Library –> Cocoa Touch Framework

 

App Layout

iPhone 480 x 320

Retina:  iPhone4  960 x 320

iPhone 5, 5c, 5s   1136 x 640

iPhone 6  1334 x 750

iPhone 6+  2208 x 1242

Universal Storyboards w Xcode 6

stare:  iPhone.storyboard & iPad.storyboard

 

Live View Rendering

od Xcode 6 także własne widoki

  • trzeba dodać atrybut @IBDesignable i nadpisać metodę prepareForInterfaceBuilder
  • dodajemy atrybut @IBInspectable to propercji, które chcemy pokazać w inspektorze

 

Debugowanie

od Xcode 6 wsparcie dla View Debugging  (jak Live DOM w VS)

 

UIKit

Size Classes - “Responsive” design w iOS 8

kompatybilność wstecz z iOS 7 (dodawany dodatkowy kod)

SizeClass enum:   Unspecified (Any), Regular, Compact

w runtime jedna dla szerokości i jedna dla wysokości

deklaratywnie

Compact (W),  Compact(H):  compact

Regular (W), Compact (H): landscape

Compact (W), Regular (H): iphone portret

Regular (W), Regular (H) ipad

Widoki UIKit

  • wiele zostało rozszerzonych pod klasy rozmiarów
  • UIImage - działa automatycznie z klasami rozmiarów, gdy jest razem z obiektem UIImageAsset
  • UISplitViewController - podział jest kontrolowany przez horyzontalną klasę rozmiaru

obiekt UITraitCollection

  • klasy rozmiaru horyzontalne i wertykalne
  • wartość skalowania

+ Auto Layout

  • klasy rozmiaru integrują się z nim
  • warunki mogą bazować na klasie rozmiaru
  • Xcode 6:  wsparcie dla klas rozmiaru w warunkach

+ Views

  • widoki mogą być instalowane/usuwane na podstawie klasy Size

pasek na dole pod designerem:  w  h

na dole bocznego paska z właściwościami:  check installed (+ dodajemy warunek),  check przy installed decyduje o widoczności

Size Inspector:  Constraints   This Size Class  (ustawiamy względem klasy Size)

można też w kodzie:

view

public override func traitCollectionDidChange (previousTraitCollection: UITraitCollection?)  {

let c = self.constraints().filter {

        el –> Bool in

        if el.firstAttribute == NSLayoutAttribte.Width {

                  return true

        }

         return false

}

if let realC = c[0] as? NSLayoutConstraint {

        self.layer.cornerRadius = realC.constant / 2

}

}

 

iOS Extensions

  • wystawienie funkcjonalności jednej aplikacji dla innych
  • wcześniej tylko deep linki
  • iOS 8 (także OSX Yosemite)

Typy

  • Share (np. obrazek)
  • Actions (np. potrzebujemy aplikację do edycji obrazka, audio, …)
  • Photo Editing
  • File Provider
  • Document Provider
  • Today (własne UI do panelu Today w centrum notyfikacyjnym)

Extension Points

  • zdefiniowane w System Frameworks
  • kontrolują sposób uruchamiania oraz czy extension wyświetla View czy jest niewizualne

Model wykonywania  extension

  • ładowane w innym, zarządzanym przez system procesie niż aplikacja
  • ładowanie do Extension Host, każda instancja extension do osobnego hosta
  • proces extension jest izolowany, ale korzysta z grup aplikacji, może przekazywać klucze, domyślnego usera .itp

Extension Context

  • zamiast delegatu UIApplication, główny obiekt w extension
  • propercja view controllera extension

Today extension

  • view controller
  • ładować możliwie najszybciej
  • centrum notyfikacyjne ustawia ramki
  • rozmiary – autolayout lub za pomocą setPreferredContentSize
  • animacja rozmiarów za pomocą viewWillTransitionToSize
  • protokół NCWidgetProviding do aktualizacji zawartości

szablon: iOS –> Application Extension –> Today Extension

*.appex

Supporting Files:  Info.pblist  - definicja wspieranego protokołu URL

obsługa otwarcia aplikacji przez plik

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

func application(application: UIApplication, handleOpenURL url: NSURL) –> Bool {

         …

         return true;

}

}

view controller:

let url = “mytoday://newsstoryid”

if let realURL = NSURL(string: url) {

self.extensionContext !.openURL (realURL, completionHandler: nil)   //otwieramy naszą aplikację

}

 

Touch ID

KeyChain - specjalizowana baza używana głównie do przechowywania haseł

Access Control List

  • aplikacje w tej samej grupie dla keychain
  • zabezpiecza przed innymi aplikacjami

TouchID

dodany do iOS z iPhone 5s i iOS7

odciski palców jako dodatkowy mechanizm autentykacyjny

teraz może być użyty jako dodatkowa warstwa ochrony elementów keychain

Local Authentication – udowadnia, że użytkownik korzysta z aplikacji

 

 

iOS 9

  • UIKit
  • Xcode 7
  • Swift 2
  • nowe API

 

UIKit

  • UIStackview
  • UIKitDynamics
  • UILayoutGuide
  • Multitasking

UIStackView

automatycznie zakłada constrainty na ciągły układ elementów w kolumnie lub wierszu

orientacja, wyrównanie, sposób wypełnienia kontenera przez elementy (np. rozciągnięte), odstępy

let aStackview: UIStackView = UIStackView()

let aView = UIView()

aStackview.addArrangedSubview(aView)

aStackview.removeArrangedSubview(aView)

aView.removeFromSuperview()

automatyczna enkapsulacja zaznaczonych elementów po wybraniu Stackview

UIKitDynamics

od iOS7 (fizyka)

nowości:

UIFieldBehavior – wektor siły na element

rodzaje:

  • linear
  • radial
  • custom (np. siły z 2 stron)

let radialGrav:UIFieldBehavior = UIFieldBehavior.radialGravityFieldWithPosition(CGPointZero)

radialGrav.region = UIRegion.infiniteRegion()

radialGrav.strength = 0.5

radialGrav.falloff = 0.2

radialGrav.minimumRadius = 0.4

UIDynamicAnimator

ImageView

User Interaction Enabled

view controller:

private var animator: UIDynamicAnimator = UIDynamicAnimator()

override func viewDidLoad()  {

self.animator = UIDynamicAnimator(referenceView: self.vwContainer)

let imgTap = UITapGestureRecognizer(target: self, action: “enableNoise:”)

self.imageAvatar.AddGestureRecognizer(imgTap)

}

func enableNoise(tap: UITapGestureRecognizer)  {

let noiseField = UIFieldBehavior.noiseFieldWithSmoothness(5, animationSpeed: 1)

noiseField.addItem(self.imgAvatar)

       let boundsCollision = UICollisionBehavior(items:  [self.imgAvatar])

       boundsCollision.translatesReferenceBoundsIntoBoundary = true

       self.animator.addBehavior(noiseField)

self.animator.addBehavior(boundsCollision)

}

coś uwalniamy palcem i jak dotknie granicy, to się odbije i wróci do centrum

 

UILayoutGuide

Prostokątna przestrzeń, która wchodzi w interakcję z layoutem.

Definiowanie warunków na widok kontenera bez zaśmiecania hierarchii widoków.

  • layoutMarginGuide
  • readableContentGuide  (w orientacji pionej tekst u góry w kilku liniach, w orientacji poziomej w jednej linii centralnie)

let guideRef = self.view.layoutMarginsGuide

let readingContentRef = self.view.readableContentGuide

let container = UILayoutGuide()

self.view.addLayoutGuide(container)

self.view.removeLayoutGuide(container)

self.view.layoutGuides

self.view.layoutMarginsGuide.trailingAnchor

Factory do tworzenia obiektów NSLayoutConstraint przy użyciu fluentnego API. Nie trzeba używać inicjalizatora z dużą ilością parametrów.

let margins = view.layoutMarginsGuide

subview.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = true

let label = UILabel()

label.translatesAutoresizingMaskIntoConstraints = false

 

Multitasking

kilka aplikacji na ekranie

3 rodzaje

  • Slide Over - z prawej strony przysnapowane okno nad aplikacją
  • Split View - podział ekranu na dwie aplikacje (osobne paski stanu, drugi ekran, wywołanie PiP, regularny;  używać auto layout, size classes, smart state transition)
  • Picture in Picture - mały ekran z video nad aplikacją (Audio & AirPlay, używać AVKit, AVFoundation, WebKit, MPMoviePlayerViewController, MPMoviePlayerController)

kompatybilność iPad

iPad Mini 2 & 3:  Slide Over, PiP (picture in picture)

iPad Air:  Slide Over, PiP

iPad Air 2:  Splitview, Slide Over, PiP

włączenie:

  • Launch Screen capability
  • wspierać wszystkie orientacje

wyłączenie:

  • UIRequiresFullscreen

wywoływana funkcja w aplikacji:

func applicationWillResignActive(application:  UIApplication)   [utrzymywać stan aplikacji]

 

Xcode 7

  • Storyboard References
  • wsparcie dla plików nagłówkowych
  • Playground Additions
  • App Thinning

Storyboard references

podział na małe, stawne instancje

let storyboard = UIStoryboard(name: “A_Storyboard”, bundle: NSBundle.mainBundle())

let viewController = storyboard.instantiateInitialViewController()

if let viewController = viewController  {

self.presentViewController(viewController, animated: true, completion: nil)

}

Storyboard Reference

przeciągamy na designer ze Storyboard

łączamy controller z referencją (Storyboard, Referenced ID, Bundle)

albo

zanaczamy kontroler, Editor –> Refactor to Storyboard…

nowy storyboard zawiera poprzednio wskazany kontroler

główny storyboard odnosi się do nowego storyboard zamiast wskazanego kontrolera

 

pliki nagłówkowe (Swift)

zalety plików .h bez ich minusów

plik Swift:  Navigate –> Jump to Generated Interface

 

App Thinning

  • Slices - na różnych urządzeniach nie są potrzebne te same assety (np. obrazki)
  • Bitcoin - AppStore odpowiedzialny za ostateczną kompilację (różne procesory armv6, armv7, armv7s, optymalizacje)
  • zasoby na żądanie - hostowane w AppStore i pobierane w razie potrzeby (NSBundleResourceRequest)

 

Nowe API

 

Contacts & ContactsUI

nowe API w miejsce starego opartego na C  (Address Book deprecated)

CNContact

  • nazwa
  • email
  • numer telefonu

CNLabeledValue - złożone typy

import Contacts

let homeEmail = CNLabeledValue(label: CNLabelHome, value:  “xxx@yyy.co”)

CNContactPickerViewController

wybór kontaktu:

view controller:  UIViewController, CNContactPickerDelegate

// import ContactsUI

let contactPicker = CNContactPickerViewController()

viewDidLoad:

contactPicker.delegate = self

contactPicker.displayedPropertyKeys = [CNContactPhoneNumbersKeys]

action:

self.presentViewController(contactPicker, animated: true, completion: nil)

func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) {

let contact = contactProperty.contact

let phoneNumber = contactProperty.value as! CNPhoneNumber

//contact. givenName,  contact.familyName,   phoneNumber.stringValue

dodanie nowego kontaktu:

let contact = CNMutableContact()

contact.givenName = “xxx”

contact.familyName = “yyy”

let homeAddress = CNMutablePostalAddress()

homeAddress.street = “…”

contact.postalAddresses = [CNLabeledValue(label: CNLabelHome, value: homeAddress)]

let store = CNContactStore()

let saveRequest = CNSaveResquest()

saveRequest.addContact(contact, toContainerWithIdentifier: nil)

do  {

try store.executeSaveRequest(saveRequest)

}

catch {

}

 

Search API

znajdowanie informacji wewnątrz aplikacji, nawet jeśli nie jest zainstalowana

  • NSUserActivity
  • Core Spotlight Framework
  • Web Markup

 

SFSafariViewController

  • standardowy interfejs do przeglądania web
  • funkcjonalności Safari (Reader, AutoFill, Fraudulent Website Detection, klucze, cookies, dane, blokowanie zawartości)

import SafariServices

let svc = SFSafariViewController(URL: NSURL(string: “https://xxx.yyy.com”))

self.presentViewController(svc, animated: true, completion: nil)

Brak komentarzy: