- Sette opp et nytt iOS prosjekt i XCode
- Komponentene i en iOS app
- Launch flow
- Application lifecycle
- MVC
- View og view controllers
Single View = tilnærmet tomt prosjekt
Søk etter "Icon and Image Sizes" i dokumentasjon for oversikt over størrelser og krav
Består av image sets/icons/launch icons, og de forskjellige variantene som brukes på forskjellige enheter
- Bilder kan lastes fra kode med:
UIImage(named: "ocean")
- Bilder kan settes fra Interface builder, eksempelvis med å lage et UIImageView som du igjen setter bildet på:
Best practise: Lag et bilde/xib som er lik første skjermbilde i applikasjonen, men uten innhold. Dette for å gi en illusjon av at appen starter raskere:
Bad practise:
- Splash screen
- Brandingelementer (eks. stor logo)
- Apple docs (XCode -> Help -> Documentation and API reference):
- App Programming Guide for iOS
- The App Life Cycle
- View Programming Guide for iOS
- View Controller Programming Guide for iOS
- App Programming Guide for iOS
- ALT-klikk på symbol for å åpne quick help
- Klikk på linken i "Reference" for å gå til class reference
- Sett cursor i symbol
- Velg quick help i inspectoren
- Hver app har nøyaktig en (singleton), som blir opprettet av UIApplicationMain
- Aksesseres med
UIApplication.sharedApplication()
- Håndterer eventloop og høynivå funksjonalitet
- Informerer om state transitions og eventer via app delegate, som er stedet du har mulighet til å håndere disse
- Går hånd i hånd med UIApplication, og er stedet hvor du håndterer app events
- App initialisering (eks, views, initielle data)
- Håndterer state transitions
- Håndterer høynivå app events (eks. push-notifications)
- Som regel bare ett, med mindre man har innhold på flere skjermer
- Manipuleres ikke direkte. I stedet bruker man View Controllers, som igjen oppdaterer viewene som vises i UIWindow
Håndterer et view og dens subview, koordinerer eventer og kommunikasjon mellom modeller og views
- Tegner innhold på skjermen
- Reagerer på events
- UIKit inneholder standardviews (labels, text fields, tables, etc.)
- Kan subklasse UIView for å lage custom views
// main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
// 1. Oppretter UIApplication singleton og AppDelegate
// 2. application:didFinishLaunchingWithOptions: i delegate blir senere
// kalt av UIApplication
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
// AppDelegate
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
// bruker .xib til å sette opp GUI (også old school)
// mer om oppsett av view senere
let vc = DemoViewController(nibName: "DemoViewController", bundle: nil)
window?.rootViewController = vc
window?.makeKeyAndVisible()
return true
}
// @UIApplicationMain kaller UIApplicationMain() og bruker denne
// klassen som appdelegate
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Gjør automatisk:
// - Oppretting av UIWindow
// - Laster main storyboard
// - Setter initiell VC fra storyboard på UIWindow
// - Viser vinduet
return true
}
}
- Inactive: i forgrunnen, men mottar ikke eventer (eks. ved inkommende anrop)
- Active: normalstate. I forgrunn og mottar eventer
- Background: Mulighet for å kjøre enkelte operasjoner i bakgrunnen (eks. lyd) / Ved launch inn i background (eks. background fetch, push)
- Suspended: I minnet, men kjører ingen kode
- Det er forventet at apper starter på maks 5 sekunder, i motsatt fall kan appen bli terminated.
- Maks 5 sekunder til å kjøre kode før suspended
- Kan be om mer tid for enkelte oppgaver med
beginBackgroundTaskWithExpirationHandler:
- Views: knapper, tekstfelt og andre komponenter synlige for brukeren
- Models: holder på data. Eks. arrays, dictionaries. Har ingen kjennskap til views
- Controllere:
- kan motta hendelser fra views
- kan oppdatere modeller
- kan oppdatere views med modelldata
Bilde: The Big Nerd Ranch Guide, kap. 1
- Du setter aldri views direkte på UIWindow selv. I stedet setter man en view controller på UIWindow, som igjen vil legge sine views til vinduet
- View controllere og ressursstyring:
- Laster bare inn viewet sitt når det trengs
- Kan deallokere viewet, f.eks. ved lite minne
- View Controllere vil typisk bare kjenne til en del av applikasjonen, og vil derfor kommunisere med andre view controllere
- Views sender meldinger til sin VC. Eksempelvis når du trykker på en UIButton kan det sende en melding til sin VC, som definerer hva som skal skje
- Content view controllers: "vanlige" view controllere du definerer for å vise/hente data fra bruker
- Container view controllers: inneholder andre view controllere, eks. UINavigationController, UISplitViewController
- Via kode
- XIB (old school)
- Storyboards
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = CustomViewController()
window?.makeKeyAndVisible()
return true
}
class CustomViewController: UIViewController {
// 1. override loadView
override func loadView() {
// 2. alloker et view. Størrelsen blir justert av parent
view = UIView(frame: UIScreen.mainScreen().applicationFrame)
view.backgroundColor = .blackColor()
// 3. opprett subviews
let button = UIButton(frame: CGRectMake(0, 100, view.frame.width, 50))
button.setTitle("Hello world", forState: .Normal)
button.addTarget(self, action: "sayHello", forControlEvents: UIControlEvents.TouchUpInside)
// 4. legg til subviews
view.addSubview(button)
}
func sayHello() {
println("Hello world")
}
}
Koble view og view controllere sammen via assistant editor
- Outlets - referanser til UI elementer fra kode (manipulere/hente ut verdier)
- Targets - referanser fra UI til kode (kalle metoder)
Ferdig eksempel: action sayHello kalles når knappen trykkes på, og setter verdien på label (outlet)
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = CustomViewController(nibName:
"CustomViewController", bundle: nil)
window?.makeKeyAndVisible()
return true
}
XIB (uttales sib) og storyboards kompileres til NIB:
The contents of .xib and .storyboard files are stored by Xcode in XML format. At build time, Xcode compiles your .xib and .storyboard files into binary files known as nibs. At runtime, nibs are loaded and instantiated to create new views.
- Apple Docs
- Standardmåten å lage views på
- Kan gi deg et overblikk over flyten i applikasjonen
- Muliggjør drag'n'drop for å koble view controllere sammen (kalt segues - på norsk: naturlig overgang)
- View controllere instansieres automatisk med verdiene fra interface builder når de trengs
- Åpne
Main.storyboard
og opprett GUI på samme måte som med XIB - Oppdater
application:didFinishLaunchingWithOptions:
til
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
3 - Sett Main interface i prosjektet:
1 - Dra og slipp "View Controller" inn i storyboard fra Object Library:
2 - File -> New -> File -> Cocoa Touch, subclass of UIViewController
3 - Koble view controller objektet i storyboard sammen med sin faktiske klasse (fra steg 2)
- Destination controller: eksponerer properties for data/presentasjon
- Source: setter properties på destination controller før den blir vist
- Når destination controller har behov for å kommunisere tilbake, gjøres dette via en delegate som sourcen oppgir. Destination controller har dermed ikke direkte kjennskap til sine foreldre
import UIKit
class ViewController: UIViewController {
// Referanse til inputfeltet
@IBOutlet weak var message: UITextField!
// Kalles når man trykker på "Send melding"
@IBAction func sendMessage(sender: AnyObject) {
// Instansierer ny vc fra storyboard MANUELT for å vise hvordan
// Normalt lar vi storyboard gjøre dette for oss. Se alt 2. senere.
if let vc = storyboard?.instantiateViewControllerWithIdentifier("receivingVC")
as? ReceivingViewController {
// Setter property på destination vc
vc.message = message.text
// Før den vises
presentViewController(vc, animated: false, completion: nil)
}
}
}
Connections inspector skal se slik ut:
// Den andre view controlleren
class ReceivingViewController: UIViewController {
// Denne må settes av parent view controller
var message: String?
@IBOutlet weak private var messageLabel: UILabel!
// Konfigurerer viewet, etter at det er lastet inn i minnet
// Funker både for views som lastes fra nib (storyboard/xib)
// og for de laget med ren kode (loadView:)
override func viewDidLoad() {
super.viewDidLoad()
messageLabel.text = message
}
}
Connections inspector skal se slik ut:
Kan lage connections mellom view controllere med drag'n'drop i storyboard. Disse overgangene kalles segues.
// Kun denne view controlleren oppdateres. ReceivingViewController
// er uendret
class ViewController: UIViewController {
@IBOutlet weak var message: UITextField!
// Kalles før overgangen skjer
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let vc = segue.destinationViewController as? ReceivingViewController {
vc.message = message.text
}
}
}
##[fit] Se Øvingsoppgavene