iOS Programming Intro

112
IOS DEVELOPMENT INTRODUCTION Lou Loizides, PE MS Computing Student @ Marquette 31 Mar 2013 http:// boozall.com

description

Lectures on basic concepts for objective-C/Cocoa development. By Louis Loizides.

Transcript of iOS Programming Intro

Page 1: iOS Programming Intro

IOS DEVELOPMENT INTRODUCTION Lou Loizides, PE MS Computing Student @ Marquette 31 Mar 2013 http://boozall.com

Page 2: iOS Programming Intro

Presentations •  Class 1 – Objective C

•  Background •  Requirements •  Concepts •  Syntax

•  Class 2 – iPhone Programming •  XCode •  Cocoa Classes •  Programming With/Without IB •  Sample App

•  If you need a book, the “Big Nerd Ranch” guides to iPhone Programming and Objective C are highly recommended

Page 3: iOS Programming Intro

BACKGROUND AND CONCEPTS

Page 4: iOS Programming Intro

Objective C • Became popular on NextStep systems in the early 1980s

•  Many objective C classes start with “NS”

• Superset of C •  “Thin layer” on top of C compiler •  C code can be used anywhere within objective c source •  Compiler (LLVM) Capable of compiling C++

•  Handy for open source libraries eg. (Tesseract, OpenCV)

• Not managed •  Apps are native code, not byte code •  Understanding of memory management is important •  Apps will crash on errors – no try/catch

• Objective C is the language, Cocoa is the framework

Page 5: iOS Programming Intro

Requirements • Mac!

•  Required an Intel processor •  Provisioning profiles need to be signed on Mac to distribute or test

on a device

• XCode •  Download from Mac App Store

•  If you need to test on an iOS device: •  Developer’s account: $100/yr •  Can distribute beta apps using ad-hoc methods

•  Need phone UUIDs •  iPhone 4 or higher (3G/3GS won’t connect to XCode anymore) •  Note: Possible to run programs in the simulator without a

developers’ account

Page 6: iOS Programming Intro

Alternatives to XCode • Some alternatives to using XCode and Macs exist:

•  Mono Touch •  App Titanium •  Unity 3D •  Flash CS5 •  Phone Gap

•  The idea of Objective C is to create fast, efficient native code so these solutions aren’t the best •  Writing an iPhone app in Flash just seems like a bad idea

Page 7: iOS Programming Intro

Quirks • Use “nil” instead of null • Usually you chose a 2 char prefix for all classes in an app

•  Example: “WB” for an app called “Workbench” • @ symbol before a string is short hand for creating an

NSString from a const char* (e.g. @"test") •  Instead of true/false it’s yes/no (true/false can be used but

it’s not common) • Almost all framework objects and functions use floats –

integers are really only used in indices •  Eg. All graphics functions use floats for points •  Using floats mean you don’t have to cast as much

• NSInteger and CGFloat more common than int and float – set to compile to 32 bit or 64 bit depending on target

Page 8: iOS Programming Intro

Cocoa • Objective C is just the language – syntax, etc. • Cocoa provides the frameworks • Consists of:

•  Foundation Framework: •  Root class is NSObject •  The majority of objects •  Objective C •  Prefixed with NS, UI, others •  Compatible with ARC, autorelease

•  Core Foundation Framework: •  No root class •  C, not Obj C •  All prefixed with CF •  Must release manually using CFRelease

Page 9: iOS Programming Intro

The Stack and Heap In Obj-C • Understanding memory management is critical in Obj-C • Stack:

•  Transient storage of local primitives •  Last in, first out during functions •  Memory is released when function exits •  *Most* primitives (including pointers) will be on the stack

•  Primitives allocated with classes end up on the heap •  If it’s declared within a function will be on the stack

• Heap: •  Memory allocated for objects •  Doesn’t automatically release •  Rule of thumb (few exceptions): if “alloc” is need it’s on the heap •  Requires a pointer somewhere (either to variable or class) to find

Page 10: iOS Programming Intro

Example static int testA = 1.0f;int testB = 1;@implementation foo{ -(void)bar { float testC=1; }}

heap in object

Stack – will disappear when function is done

static allocation in heap Note: “.0f” means cast as float (usually not necessary)

Page 11: iOS Programming Intro

Pointers stack heap

0xABC111

0xABC119

0xABC11F

• Pointers are int32 memory addresses (eg. ABC111) • Mostly used for addressing classes in objective-C, but can

also be used for anything else allocated: •  Arrays in C (allocated using malloc) •  Pointers to other primitives – use to pass values “by reference”

0xABC111

Allocated Object

Page 12: iOS Programming Intro

Using Pointers Address of a variable, class, etc:

int var = 16;int &varAddress = *int;

Accessing data at pointer address:

*varAddress = 17 Allocating memory and returning a pointer:

//allocate 10 ints//Note: because this is C you will need release()int *varAddress = (*int)malloc(10*sizeof(int));

Two different ways to declare: myClass *pointer1, *pointer2; //preferredmyClass* pointer1, pointer2;

Page 13: iOS Programming Intro

Key Pointer Concepts for Obj C • Understand what’s on the stack

•  Keep track of objects on the heap

• Recognize null references •  Pointers should point to objects or nil to avoid errors •  Un-initialized primitives won’t crash program but null references will

• All objects in Obj C are allocated dynamically using pointers

•  “id” can be used in place of object pointer •  Sort of like generic “object” class in VB •  Example:

NSString* myString = [[NSString alloc] init]id sameString = myString;

Page 14: iOS Programming Intro

Quirks & Pointers Code Example NSString *str = nil; !CGFloat gV = 5.0f; !BOOL testC = NO; !!for (NSInteger i=0; i<10; i++) !{ ! testC = i>gV; ! if (testC) str = @"test”; ! //pointer will be 0x0 (nil) until it's past 5! NSLog(@"%d against %f and the pointer is %p”, ! i,gV,str); ! //a string is static so it’s always at the same ptr! //use NSMutableString if you want a copy! NSLog(@”text %@ still at %p", !

"str,[str copy]); }

Page 15: iOS Programming Intro

Classes • Classes consist of Interface (class declarations) and

Implementation (methods) • Usually two files are created for each class – one with

each •  It is technically ok to put both in the same file, but this can slow

down compiling •  It is technically ok to put multiple classes in the same file but most

people don’t (I do it every now and then)

• Most classes will inherit from another class

Page 16: iOS Programming Intro

Class Inheritance in Objective C •  Any class in objective C can derive from any class •  Any function can be overridden

•  Overriding a function requires no special syntax or keyword •  Program will first look for a function in the child class, then traverse up

the class hierarchy until it finds a match •  Don’t forget to call [super methodName] if you need to keep traversing •  Access: “super” = parent class, “self” = current class

NSObject

MyObj

-(void)test

-(void)test

NSObject

MyObj

-(void)test

No test method

Runs this one

Runs this one

Page 17: iOS Programming Intro

Headers And Interfaces •  Same concept as C, C++ •  Provides forward declaration (for compiler & IDE) of:

•  Classes •  Variables •  Selectors

•  Memory for items declared in the class interface in the header (including structs and primitives) is allocated on the heap when the class is created •  At a minimum your class needs enough space for what’s in the interface •  Everything else is allocated dynamically as needed

•  Selectors don’t have to be declared in the header, but won’t be visible to other classes unless they are

•  Variables are never visible to other classes •  Headers are just for declaring “global” variables •  Getters and setters are required to access variables from other classes

Page 18: iOS Programming Intro

Interface/Implementation Example

Header (XY.h)

@interface MyClass:NSObject{ NSInteger myInt;}//forward declare func-(void)myFunction;//static class func+(CGFloat)classFunction;@end

Implementation (XY.m)

static BOOL saveMe=YES;@implementation MyClass -(void)myFunction { } +(CGFloat)classFunction { return 1.0f; }@end

superclass

Page 19: iOS Programming Intro

Import and @class Directive •  Headers must be imported when needed •  Because every header imports it’s own headers, importing headers

within headers leads to memory problems and long compilation times •  Frameworks are imported with <> instead of quotes •  Use @class directive when possible to tell a header you’ll import the

other header in the implementation #import <CoreData/CoreData.h> //Framework#import “myHeader.h”@class someClass; //“I’ll import someClass later”@interface myViewController:UIViewController{ someClass *test;}@end

Page 20: iOS Programming Intro

Class Extensions •  In addition to creating a class derived from another class, you can

modify existing classes with class extensions •  Specify class you’re extending in the interface: •  Syntax for a class extender for UIImage called “Pixels”

"@interface UIImage (Pixels) !"@end !

!"@implementation UIImage (Pixels) !"@end !

•  If you create a class using the File menu, the template will crate a class extension at the top of the .m file – comes in handy but not necessary

"@implementation myClass () •  Common convention for class extender file name:

•  UIImage+Pixels.m •  UIImage+Pixels.h

!

Page 21: iOS Programming Intro

Class vs. Object Methods •  “-” before a method means it’s an object method •  “+” before a method means it’s a class method

•  Class messages are statically allocated when class is created •  Commonly used for a custom alloc and init

• Same concept as local/global functions in C++

• Example, for class “myClass” (methodàmessage): +(void)test{} à [myClass test]-(void)test{} à myClass *obj; [obj test]

Page 22: iOS Programming Intro

Objective C “Messages” •  In Obj C you “send messages” to objects to run methods • Comparison syntax:

•  Send message “method” to myclass in Obj C: [myClass method]

•  C++ and Java equivalents: mClass->method() myClass.method()

•  Objective C 2.0 (introduced in 2007) allows use of dot notation •  Examples in stack overflow will be mixed •  In my experience developers tend to use dot notation for getters,

standard syntax for everything else •  I don’t recommend too much dot notation as it hides what’s happening

•  “Selector” = signature of a method •  Eg: Selector for [view initWithFrame:frame] is “initWithFrame:”

Page 23: iOS Programming Intro

Passing Objects in Messages • Only primitives can be passed

•  Objects are passed using pointers

• Example Message: oClass *obj1;oClass *obj2;[myClass selectorWith:obj1 andAlso:obj2]

• Example Function: (void)selectorWith(oClass*)o1

andAlso:(oClass*)o2{ }

Functions in objC are usually very descriptive, but the words before the parameter is not necessary (only need spaces)

Would be referred to as selector “selectorWith:andAlso:”

Page 24: iOS Programming Intro

Cool Thing About Nil References •  Sending a message to an object with a nil reference just returns nil •  This can cause some headaches, though, because code will run if object

not allocated •  If a class might be nil it’s safer to send a message to that class if the

alternative is to pass a nil object to another class in a message to it (which crashes a lot of methods) •  Example:

safe: [view2 removeFromSuperview] //just returns nil if view2=nil not safe: [view removeSubView:view2] //could crash if view2=nil (note: there is no removeSubView method for this reason)

if ([myClass skyIsBlue]) { /* true if sky is blue false if sky is not blue or myClass = nil */}

Page 25: iOS Programming Intro

Common Nil Reference Mistake UIButton *tBut; //just a pointer; nothing created//this will not generate errors[tBut setTitle:@"test”

forState:UIControlStateNormal];//what’s missing – need to point to something:UIButton *tBut =

[[UIButton alloc] init];[tBut setTitle:@"test”

forState:UIControlStateNormal];

Page 26: iOS Programming Intro

Objective C Object Declaration • Standard steps are:

•  Allocate Memory •  Initialize object

• Syntax: myObj *pointer = [[myObj alloc] init];

• Many standard classes have a class method that does both steps, ex:

UIButton *t = [UIButton buttonWithType:UIButtonTypeCustom]UIColor *color = [UIColor redColor];

Page 27: iOS Programming Intro

Standard Init Methods •  Unlike in managed code, objective c objects always have to be

initialized (memory starts out as random bits) •  NSObject uses the selector “init” for this, which can be

overridden as necessary. Always follow this form:

-(id)init{ self = [super init]; if (self) {

//your stuff here //only run if super initialized ok

} return self;}

Page 28: iOS Programming Intro

Creating Custom Init Methods •  You don’t have to use provided init selector:

-(id)createClassWithHelloString:(NSString*)helloS

{ self = [super init]; if (self) {

NSLog(@”Hello String: %@”,helloS); } return self;}•  Views have initWithFrame: •  Controllers have initWithNibName:bundle:

Page 29: iOS Programming Intro

Objective C Heap Memory Management • Objects on heap need to be accounted for and

deallocated as necessary •  3 Options for Cocoa Touch:

•  Allocate and release memory manually [myObj release];

•  Add objects to autorelease pool •  Autorelease pool retains objects until program exits or when it’s

manually drained [myObj autorelease];

•  Use Automatic Reference Counting Note: Cocoa for OSX does have a GC, but we won’t be discussing it here

Page 30: iOS Programming Intro

ARC (Automatic Reference Counting) •  Introduced in 2011 • Supercedes manual reference counting • Retains objects that have “owners” (strong pointers to

object) • Only works with classes derived from NSObject (not

foundation classes or anything based on C) •  Release other classes manually using release() and CFRelease()

• Automatically deallocates objects with no owners • Can still compile individual classes without ARC:

-fno-objc-arc flag (not common)

Page 31: iOS Programming Intro

More Notes Regarding ARC • Reasons not to use it:

•  Releasing yourself can help eliminate memory problems •  ARC does not allow use of release and autorelease in code

•  Easy to create memory leaks •  ARC can take a few ms to a second to release objects

•  Program can run ok during one test and crash during the next •  Easy to miss problems and have them show up later

•  I will only be using ARC in my examples

Page 32: iOS Programming Intro

Releasing an Object in ARC • Set all owners of an object (strong pointers) to nil. Once

the object is floating and has zero owners ARC will grab it. //allocate the view UITableView *myTable = [[UITableView alloc] init]; myTable = nil;

*myTable pointer UITableView Object

*myTable pointer UITableView Object

Object has zero owners now, so ARC will reclaim

Page 33: iOS Programming Intro

ARC vs. Garbage Collection ARC Garbage Collection

Managed Not managed. ARC is code added at compile time, so very little overhead required

Managed. Part of OS that watches objects on the heap. Can lead to performance problems if too many objects are allocated.

Persistence Objects are released as soon as there’s no pointer to them. Need to be very careful about keeping track of pointers.

Objects are released as required to free up memory

Memory Leaks Prone to memory leaks if there are pointers that are unreachable in code

Less prone to memory leaks as objects that are no longer being used will be released eventually

Page 34: iOS Programming Intro

Memory Leaks in ARC •  Most common cause of a leak is through a retain cycle •  With ARC you might not have to release but setting pointers to nil is important

Obj 2

*obj3 = 0x2

Obj 3

*obj2 = 0x3

Obj 1

*obj2 = nil

Obj 2

*obj3 = 0x2

Obj 3

*obj2 = 0x3

Obj 1

*obj2 = 0x1

Obj 2

*obj3 = 0x2

Obj 3

*obj2 = 0x3

Obj 1

*obj2 = nil

All objects have owners and are retained

Obj 2 will be released (no owner), then Obj 3 (no owner once Obj 2 is gone)

Neither Obj 2 nor 3 will be released as they both own eachother

Retain Cycle

Page 35: iOS Programming Intro

Using Weak References •  Unlike strong references, weak references do not imply ownership •  Create by adding “__unsafe_unretained” before pointer declaration

•  Used to be “_weak” •  Need to be very careful with this – no guarantees against null references

•  Most times it’s better to just use strong references and break them when necessary •  Some collection classes (NSMapTable) are weak by default

Obj 2

*obj3 = 0x2

Obj 3

*obj2 = 0x3

Obj 1

*obj2 = 0x1 All objects are retained

Obj 2

*obj3 = 0x2

Obj 3

*obj2 = 0x3

Obj 1

*obj2 = 0x1 Obj 2 then 3 will be released

Page 36: iOS Programming Intro

Code Example – Objects and Memory //what's the problem here??? !//(assume this is not on the main thread)!!-(void)testAlert!{ ! UIAlertView *alert = !

" "[[UIAlertView alloc] init]; ! [alert setTitle:@"Hello!"]; ! [alert addButtonWithTitle:@"Log Awesomeness"]; ! [alert addButtonWithTitle:@"Close"]; ! [alert setCancelButtonIndex:1]; ! [alert setDelegate:self]; ! [alert show]; !}

Page 37: iOS Programming Intro

Released too soon! •  This is a common type of problem created through ARC:

1.  [alert show] tells the main thread to draw the alert box 2.  If started from another thread (like in a block somewhere) that

means it happens asynchronously 3.  So while the box is still drawing, the function ends, the frame

objects are released, and there are no more owners of “alert” •  ARC comes and releases the object before we’re done using it •  Resulting behavior can be erratic:

•  In most cases the program will crash •  In some cases if ARC is fast enough the alert box won’t show •  When ARC is slow everything might run fine

•  Users in the app store start complaining – your app is crashing!

Page 38: iOS Programming Intro

Example Crash

EXC_BAD_ACCESS There is nothing here

Probably the last frame saved just before the crash (pointer not nil yet)

Page 39: iOS Programming Intro

Getters and Setters (Accessors) • Methods to access variables from outside a class • Naming is by convention:

int myVariable;-(void)setMyVariable:(int)_myVariable{ myVariable = _myVariable;}-(int)myVariable{ return myVariable; }

Setters usually start with “set”. Underscore is only meant for synthesized setters, but everyone uses them anyway. **This example is nonatomic

getters usually have the same name as the variable

Page 40: iOS Programming Intro

Accessing Getters and Setters • Dot notation follows the conventions

-(void)setMyVariable:(int)_myVariable

{ myVariable = _myVariable;}

[class myVariable];class.myVariable;

-(void)myVariable:{ return myVariable}

[class setMyVariable:1];class.myVariable=1;

Both are valid:

Page 41: iOS Programming Intro

Notes Regarding Dot Notation •  Depends on developer •  Most objective C samples I’ve seen follow this:

•  Brackets are used in majority of cases •  Dot notion is used for getters, but not setters •  Dot notation is used when you have a ton of brackets •  This is not a convention by any means

[[self window] setRootViewController:[UIViewController alloc] init]];

//Becomesself.window.rootViewController =

[[UIViewController alloc] init];//Or most commonly[self.window setRootViewController:

[UIViewController alloc] init]];

Page 42: iOS Programming Intro

Be Careful: //say object is at 0xA123 //test.object1 points to 0xA123test.object1 = [[myClass alloc] init]; //test.object2 now points to 0xA123 alsotest.object2 = object1; //both set the color of the object at 0xA123[test.object1 setColor:[UIColor whiteColor]];[test.object2 setColor:[UIColor whiteColor]]; //this has no impact to object1, just changes //the pointer for object2 to something differenttest.object2=[[myClass alloc] init]; //traditional notation is a little clearer[test setObject2:[[myClass alloc] init];

Page 43: iOS Programming Intro

Synthesizing Getters and Setters

Header (XYClass.h)

@interface MyClass@property (atomic,

readonly) NSString *myProperty;@end

Implementation (XYClass.m)

@implementation MyClass

@synthesize myProperty;@end

•  atomic = all or nothing (better for threading) – see NSLock

•  nonatomic = partial writing of variables can happen

•  readonly = just create getter

•  Synthesize actually creates the getter, setter and the variable – if you forget “synthesize” the variable won’t exist but the program can run

•  Note: You still need to initialize the variable – synthesize won’t do that

Page 44: iOS Programming Intro

Custom Accessors •  Can either synthesize and replace (if nonatomic) or just create

your own •  See NSLock for thread locking atomic implementation (atomic is

slower but probably not by much)

@synthesize myProperty; //create both getter and setter//override getter:-(NSString)myProperty{ //if there’s no object pointed to, make one if (!myProperty) myProperty =

[NSString stringWithUTF8String:"hi!"];//note: this is equivalent to myProperty = @"hi!"

return myProperty;}

Page 45: iOS Programming Intro

Structs •  Group of primitives that are created together

•  Usually on the stack unless allocated with an object •  Members accessible through dot notation •  Commonly used in Cocoa (ex. CGRect)

typedef struct { NSInteger myInt; CGFloat myFloat;} myStruct;myStruct test;test.myFloat = 1.0f

Page 46: iOS Programming Intro

Static Variables • Static variables are allocated at runtime • Shared between classes • Use for constants

•  Preferred over compiler macros •  Unlike macros will be seen by debugger

• Possible to assign values to static variables in implementation file, but not in header

static CGFloat test=1.0f;

Page 47: iOS Programming Intro

NSLog • Extremely useful debugging tool – sends to app log •  Following conventions from C’s printf:

•  %d = integer •  %f = float, double •  %p = pointer

•  printf works with const char* - NSLog uses NSString •  printf(“test %d”,1); •  NSLog(@“test %d”,1);

• %@ will also call the description function of an object •  NSLog(@”test string %@”,myString); •  [myString description] returns string itself •  Other objects might return more details

Page 48: iOS Programming Intro

Delegates •  Delegate classes correspond to a protocol •  Any class can be declared as a delegate

•  Add <delegate name> after name of superclass in header •  Protocols contain necessary functions to run certain things //set self as a delegate for the table view[myTableView setDelegate:self]//this function defines the table row height-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 3.0f;}

Page 49: iOS Programming Intro

C Pre Processor Macros • Used to insert values before code is compiled

• Simplest form: •  #DEFINE PI 3.14f; •  Everywhere in the code where “PI” is used replaced with 3.14f

• Can be used for simple functions: •  Included a lot in frameworks •  Example: The “MIN” macro: #if !defined(MIN) #define MIN(A,B) ({ __typeof__(A) __a = (A);

__typeof__(B) __b = (B); __a < __b ? __a : __b; })#endif

Page 50: iOS Programming Intro

Static (Singleton) Classes •  There is actually no way to make a singleton class in Obj-C

•  All classes in Obj-C are allocated dynamically •  Common method is to create a static pointer and reference that

using a class function:

+(EXSingleton*)getSingleton { static EXSingleton *getSingleton= nil; if (!getSingleton) { getSingleton = [[super allocWithZone:nil] init]; } return getSingleton;}+(id)allocWithZone:(NSZone *)zone{ return [self getSingleton];}

Alloc calls allocWithZone, so overriding this is just a way of getting the normal alloc method to return the singleton – it’s not 100% necessary. You can just call [myClass getSingleton] to get/create the singleton

Page 51: iOS Programming Intro

Blocks •  Use to pass function with variable frame values from one

selector to another •  Very common with asynchronous functions •  How to define: typedef void (^blockName)(blockParam* pName); typedef void (^blockName)(void); //no params //blockName can now be passed like a variable•  Where you’ll need it (ex. defining what happens after pushing a

new view controller onto the stack) [self presentViewController:coolViewController animated:NO completion:^{ //put code to be run //at completion here }];

Page 52: iOS Programming Intro

Referencing Selectors •  Use @selector(selectorName:) syntax to reference

selectors •  Used in timers, multi-threading, etc to fire a selector •  Don’t forget to colons for each parameter passed to the

selector or the app will crash (invalid signature)!!!

NSThread *newThread = [[NSThread alloc] ! initWithTarget:self! selector:@selector(mySelector:) ! object:nil]; !!//Points to: !-(void)mySelector:(id)testObject {}

Page 53: iOS Programming Intro

COCOA TOUCH PROJECTS

Page 54: iOS Programming Intro

MVC – Model View Controller • Model = “Stuff in background”

•  Creates notifications •  Provides data •  Doesn’t know anything about user, GUI, etc

• View = Visual / GUI elements •  Same concept in Android •  No knowledge of what they’re displaying just how to display it

• Controller = Logic •  Coordinates between model and view objects •  Similar to activities in Android •  Several different methods of pushing controllers onto a stack

Page 55: iOS Programming Intro

Starting Your Project •  File > New Project

Stick to these

Page 56: iOS Programming Intro

Add Options

Check this

If you’re a developer this should match your account

This can be added later

Page 57: iOS Programming Intro

Necessary Files • main.m (required)

•  Creates the run loop (the main thread) •  Usually creates the autorelease pool for ARC

• App Delegate (required) •  Usually named “XYAppDelegate.m, XYAppDelegate.h” •  Contains delegate functions called by OS to:

•  Create GUI after launch: application:didFinishLaunchingWithOptions:•  Go to sleep: applicationDidEnterBackground:•  Exit program: applicationWillTerminate:•  Etc.

• Main View Controller •  Usually named “XYViewController.m, XYViewController.h” •  Necessary to display something

Page 58: iOS Programming Intro

Key GUI Elements •  3 Panes: Controls content in left pane

Controls content in right pane

Page 59: iOS Programming Intro

How Projects are Organized • All files are in a single folder •  Things that look like folders are actually “groups”

Group

Startup Images

Page 60: iOS Programming Intro

Key Graphics Concepts • Startup images are displayed when an app is starting

•  Not recommended for use as a splash screen – amount of time they’re displayed varies (Apple recommends a screenshot)

• Graphics for standard and retina displays can be mixed: •  Use normal image names for standard •  Add “@2x” to retina images – app will find them

• Screen resolution for retina is double that of standard •  Point size comes from standard but with a screen scale of 2 •  Eg: iPhone 3G/3GS iPhone 4

Screen resolution 320 x 480 640 x 960 Screen points 320 x 480 320 x 480 Screen scale 1 2

Page 61: iOS Programming Intro

IB and NIB/XIB Files •  Interface Builder (IB) is a way of graphically laying out views to be

used by a view controller •  XIB is XML version, NIB is compiled (same concept as XAML) •  Linked to a class, but not an object – if a view controller is initialized

with a nib it’ll map to the nib as required •  Views can also be created from a NIB

•  But be careful as this is usually not efficient (you’re loading and interpreting a file every time)

•  Never ever ever EVER create table view cells from a NIB •  Could be useful for laying out something like a tip window

•  I stay away from IB – I find it’s more reliable to lay out views programmatically •  IB won’t handle complex changes between portrait and landscape •  When the iPhone 5 came out all of my apps scaled automatically

•  Two non-obvious advantages IB •  Apple’s human interface guidelines are built in •  You can include key-value pairs in views

Page 62: iOS Programming Intro

Linking NIBs to view controllers •  First must set “File’s Owner” to the class you’re using it for (eg. ExViewController) •  Linked to view/view controller through IBOutlet property •  Actions can be linked through IBAction, but just as easy to do programmatically

This connection is made when the class is initialized with the NIB (if there’s no NIB loaded it’s not made)

Page 63: iOS Programming Intro

Breakpoints and Frames •  Breakpoints can be symbolic or exception

•  Possible to break on all exceptions if desired •  Frame is shown at breakpoint

Threads

Stack frame

gdb debug shell

Breakpoint

Page 64: iOS Programming Intro

iOS Simulator / Schemes • Not an emulator

•  Apps are compiled for x86 •  Different versions of iOS can be added

•  Go to preferences > components to add

• Use schemes to: •  Add debuggers •  Add launch arguments

Page 65: iOS Programming Intro

Logs • Records output

from: •  Compiler •  NSLog •  OS •  Other debugging

tools

• All logs throughout a single XCode session are saved

Logs

Current output window

Page 66: iOS Programming Intro

Frameworks •  Frameworks can be added as necessary to any

implementation or header and won’t throw an error: <CoreData/CoreData.h>

•  Frameworks still need to be linked to the project •  If they’re used but not linked, you’ll get a linker error when trying to

compile •  To add a framework, go to:

•  Target > Summary > Linked Frameworks

•  Or Target > Build Phases > Link Binary with Libraries

Page 67: iOS Programming Intro

Help •  2 Sources:

•  Quick help (in right pane) •  Easy to inspect framework headers

(very useful) •  Detailed help (in organizer)

•  Can get to detailed help from quick help

•  Definitely not as good as MSDN – no short code examples, just sample projects

•  Most useful section is the list of selectors

Go to organizer help

Page 68: iOS Programming Intro

Organizer • Contains documentation (help), archives and device

management • Use Devices tab to copy provisioning profiles to devices

for testing, or enable testing on certain devices • Create archives to upload to the app store or for ad-hoc

distribution • Delete derived data in projects to fix problems (contains

pre-compiled headers) •  Can also go to Product > Clean

Page 69: iOS Programming Intro

KEY COCOA CLASSES

Page 70: iOS Programming Intro

NSString/NSMutableString • Objective C classes for holding and manipulating unicode

strongs • NSString is always static • Using shorthand @”” declares an NSString using UTF8

characters

Page 71: iOS Programming Intro

NSDictionary/NSMutableDictionary • Collection classes

•  Own objects they contain

• NSDictionary – can’t change • NSMutableDictionary – can change • Hold lists of pointers – can contain any object • Similar to arrays, but access value by key not index myDict = [[NSMutableDictionary alloc] init];[myDict valueForKey:@”test”][myDict setValue:myClass forKey:@”test”]

Page 72: iOS Programming Intro

Arrays / Sets • Collection Classes

•  Own objects they contain • NSArray, NSSet – can’t change • NSMutableArray, NSMutableSet – can change • Hold lists of pointers – can contain any object • Arrays: values accessible by index myArr = [[NSMutableArray alloc] init];[myArr objectAtIndex:1][myArr setObject:myClass atIndexedSubscript:1]

• Sets just hold non-indexed collections of objects •  Used for core data stores •  Use whenever you don’t need an index (significantly faster)

•  Eg. holding pointers to retain them

Page 73: iOS Programming Intro

Fast Enumeration • All collections support fast enumeration:

for (NSString* checkString in stringArray) { if ([checkString isKindOfClass:

[NSString class]) { NSLog(@”it’s a string!”);

}}

Always smart to check classes when using fast enumeration

Page 74: iOS Programming Intro

UIViewController • Root class that all view controllers are based on • Generally override initWithNibName:bundle to init • Use to push view onto the view controller stack: -(void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion

• Use to remove self from the view controller stack: -(void)removeFromParentViewController

• UINavigationController can also be used with a view controller to manipulate the stack (creates the standardized looking toolbars on the top and bottom of the screen)

Page 75: iOS Programming Intro

NSNumber / NSValue • Objective C collections (and other classes) are based on

pointers, so they can’t store primitives • NSNumber can hold any type of numeric value in an

object wrapper and contains other functions for converting strings to numbers, etc.

• NSValue serves the same purpose, but it’s just a wrapper for primitive values

Page 76: iOS Programming Intro

Some GUI Views (all derived from UIView) UIView Root class for views UIButton Button

(use class selector [UIButton buttonWithType:] to init)

UIImageView View for displaying UIImage ULlabel Simple text label UITextField Field for editing text UIScrollView Scrolling window view UITableView Creates a table (only contains

UITableViewCell objects as rows – no columns)

UITableViewCell Creates table cells for UITable

Page 77: iOS Programming Intro

NSURL / Downloading Internet Data •  Use NSURL to link to a URL

"NSURL *postURL = [NSURL URLWithString: !"@"http:www.google.com/image.jpeg"]; !

•  Use NSURLRequest (or mutable) to set up a net request "NSMutableURLRequest *request = "!"[NSMutableURLRequest requestWithURL:postURL!"cachePolicy:NSURLCacheStorageNotAllowed!"timeoutInterval:60.0]; !

•  Send an asynchronous (or synchronous) request "[NSURLConnection sendAsynchronousRequest:request!"queue:[NSOperationQueue mainQueue] !"completionHandler:^(NSURLResponse *response, !"NSData *data, NSError *error) { !" "if (error) {} !" "//downloads to NSData; add your stuff here !"}];

Page 78: iOS Programming Intro

BASIC COCOA PROGRAMMING WITH IB

Page 79: iOS Programming Intro

Adding a View Controller & Nib • Add an Obj C class derived from UIViewController • Select “With XIB for user interface” • Alternatively – add a User Interface with a UIView

Page 80: iOS Programming Intro

The XIB Owner and First Responder •  The owner is the class that will own the NIB

•  Example: “EXViewController”

•  The first responder is the object that receives an action •  Example: A view you click on •  If the responder doesn’t handle the event it propagates down the

responder chain: •  View > View Controller > Window > Application

•  You can change the first responder, but it’s usually not necessary

Page 81: iOS Programming Intro

Setting the Owner •  Click on “File’s

Owner” in the XIB window

•  Select the property inspector on the right pane

•  Change the class to your view or controller that the Nib will be dropped into •  Example:

EXViewController

Page 82: iOS Programming Intro

Add Views to the NIB • Drag views from objects in right pane • Use guides to stick to Apple’s Human Interface Guidelines

Page 83: iOS Programming Intro

Connecting Views to the Controller •  Open an assistant

editor window (the guy in the tux) to have something to drag views to

•  Close the right pane if necessary to make space

•  Open the header of your view controller in the assistant window and the xib in the main window

•  Drag the views into the header of your view controller while holding down command

Page 84: iOS Programming Intro

Creating an IBOutlet and IBAction • After dragging, name the item and add an outlet/action • An outlet creates a property with a pointer to the object • An action creates a selector that’s called through interaction

with the object (eg. Touch Up Inside, Touch Down)

Page 85: iOS Programming Intro

IB Code Added •  IBOutlet *testButton pointer points to the button created

by the nib •  IBAction touchButton adds code to the header and

implementation that can be used to add code when the button is pressed

Filled in circle means this outlet is connected to something in the nib

Page 86: iOS Programming Intro

Adding an Action to the Button •  Assume we’ve added an IBOutlet property for the label as well

– UILabel *testLabel •  Pressing the button will set the label text to “Hello World” and

the view controller’s view to a red background •  @implementation EXViewController!

•  - (IBAction)touchButton: ! (UIButton *)sender { ! [self.testLabel setText:@"Hello World"]; ! [[self view] setBackgroundColor: !

" "[UIColor redColor]]; !}

Page 87: iOS Programming Intro

Loading The Nib After App Launch //Note: This is all in the single window template… //1. Import ExViewController.h into the app delegate#import "EXViewController.h" //2. Use delegate application:didFinishLaunchingWithOptions- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //3. Create a UIWindow to display the app inUIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //4. Create the root view controller & add the nib name (no // extension or leave nil for no nib (can also just use "init")myViewController *rootViewController = [[myViewController alloc] initWithNibName:@"myNib" bundle:nil]; //5. Set the UIWindow’s rootViewController property to itwindow.rootViewController = rootViewController; //6. Set the UIWindow as the key window[self.window makeKeyAndVisible];}

Page 88: iOS Programming Intro

Result

Press Button

Page 89: iOS Programming Intro

COCOA PROGRAMMING WITHOUT USING IB

Page 90: iOS Programming Intro

Reasons Against Using IB •  IB is slow

•  Nib has to be loaded and interpreted to create layout •  Only provides benefits for starting layout

•  You’ll end up writing code to manipulate all of the views anyway •  Easy to break links to Views •  Lack of flexibility for rotations

•  Pretty much have to stick to the standard automatic layout properties – can’t have two complex layouts

•  I have trouble getting the auto layout properties to work the way I want them to, but that might just be me (there are books on the subject)

•  Need different Nibs for both iPad and iPhone •  What happens if the screen size ever changes?

•  When the iPhone 5 came out my apps all scaled fine •  Still an unreasonable number of apps in the app store that have black

bars on the bottom and top of the iPhone 5 window •  I don’t use it… so I can’t teach you much about it

Page 91: iOS Programming Intro

View Frames •  Every view has a frame to set the location and size •  The frame is stored in/set using a CGRect structure, which

contains a CGPoint specifying the origin and a CGSize specifying the frame size

struct CGRect { CGPoint origin; CGSize size;};struct CGPoint { CGFloat x; CGFloat y;};struct CGSize { CGFloat width; CGFloat height;};

Page 92: iOS Programming Intro

View Frame Example //graphics in iOS are usually//done with floats, not ints//remember these are structs//so must use dot notationCGPoint origin;

origin.x=10;origin.y=20;

CGSize size;size.width=100;size.height=200;

CGRect frame;frame.origin=origin;frame.size=size;

origin.y

orig

in.x

size

.hei

ght

size.width

view

superview

Page 93: iOS Programming Intro

More on CGRect •  CGRectMake can be used to make a CGRect in one line CGRect CGRectMake ( CGFloat x, CGFloat y, CGFloat width, CGFloat height); •  Also see CGPointMake, CGSizeMake

•  CGRectZero is a frame of all zeros •  A view make with CGPointZero would not be visible •  Also see CGPointZero, CGSizeZero

•  CGRects are structures not objects, so you can make copies using dot notation. But on a view they’re read only so you need to use a setter to set the entire frame at once (the superview redraws it’s subviews when a new frame is set) CGRect newFrame = obj1.frame;newFrame.height+=100;[obj2 setFrame:newFrame]; //or obj2.frame=newFrame;

Page 94: iOS Programming Intro

Adding a View With a Frame - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) {

//helpful to set a pointer to the controller’s view but not necessary UIView *selfView = [self view]; CGRect selfFrame = [selfView frame]; CGRect textFrame = selfFrame;

//this is the size of our text box textFrame.size = CGSizeMake(100, 100);

//some basic math to center it in the screen textFrame.origin =

CGPointMake((selfFrame.size.width-textFrame.size.width)/2, (selfFrame.size.height-textFrame.size.height)/2); UITextView *textBox = [[UITextView alloc] initWithFrame:textFrame];

//add some attributes [textBox setText:@"Hello World"]; [textBox setBackgroundColor:[UIColor colorWithWhite:0.8f alpha:1.0f]];

//don’t forget to add the textbox as a subview! [selfView addSubview:textBox]; } return self;}

Page 95: iOS Programming Intro

Helpful Tip – Don’t Set Frames In Init • Make it easy to redraw views when calculations change

•  Example: Screen rotation (note: you can also use autorotation, but I find that it’s never easy to get it working perfectly)

•  For init just set all frames to CGRectZero •  For view controllers create a selector like “CreateFrames”

and call it at the end of init •  Now you can call it again whenever you need to

•  For views, just override the view’s setFrame: selector •  Note: Don’t forget to call the super’s setFrame: selector also or the

view won’t redraw frames properly

Page 96: iOS Programming Intro

Adding Targets to Views (eg. Buttons) - (id)initWithNibName:(NSString *)nibNameOrNil!

"bundle:(NSBundle *)nibBundleOrNil { ! self = [super initWithNibName:nibNameOrNil!

"bundle:nibBundleOrNil]; ! if (self) { !

"testButton = //declared in interface!" "[UIButton buttonWithType:UIButtonTypeCustom]; !

[testButton setFrame:CGRectZero]; ! [testButton setTitle:@"Test" forState:UIControlStateNormal]; ! [testButton addTarget:self action:@selector(mySelector:) ! forControlEvents:UIControlEventTouchDown]; !

"[self setFrames]; //my own method to set view frames !"[[self view] addSubview:testButton]; !"} !

return self; !} !

-(void)mySelector:(id)buttonObject { ! NSLog(@"I pressed button %@",buttonObject); !}

target = object to send message to

2013-03-31 14:58:33.307 Example[2825:c07] I pressed button <UIButton: 0x8868510; frame = (10 10; 100 100); opaque = NO; layer = <CALayer: 0x8868640>>

Page 97: iOS Programming Intro

Adding Actions to Views Without Targets •  Two common options:

•  UIGestureRecognizer UISwipeGestureRecognizer *recognizer; ! recognizer = [[UISwipeGestureRecognizeralloc] ! initWithTarget:self! action:@selector(handleSwipeFrom:)]; ! [recognizer setDirection: ! (UISwipeGestureRecognizerDirectionRight! | UISwipeGestureRecognizerDirectionLeft)]

•  Overriding touch selectors •  Every view contains touch tasks. See UIResponder documentation for

more info (UIView inherits from UIResponder). Examples: •  touchesBegan:withEvent: •  touchesMoved:withEvent:

•  Note: Gesture Recognizers can cancel touches •  Set cancelsTouchesInView property

Page 98: iOS Programming Intro

APP EXAMPLE GPS Tracker

Page 99: iOS Programming Intro

Create the Project

Page 100: iOS Programming Intro

Create A Root View Controller

Page 101: iOS Programming Intro

Add A View Controller Property To The App Delegate // !// GTAppDelegate.h!// GPSTracker!// !// Created by Louis Loizides on 3/31/13.!// Copyright (c) 2013 Louis Loizides. All rights reserved.!// !

#import <UIKit/UIKit.h> !

@class GTViewController; !@interface GTAppDelegate : UIResponder <UIApplicationDelegate> !

@property (strong, nonatomic) UIWindow *window; !

// Don’t forget to synthesize this in the implementation!!@property (nonatomic) GTViewController *rootViewController; !

@end

Page 102: iOS Programming Intro

Create The View Controller // !// GTAppDelegate.m!// GPSTracker!#import "GTAppDelegate.h" !#import "GTViewController.h" !

@implementation GTAppDelegate!@synthesize rootViewController; !

- (BOOL)application:(UIApplication *)application ! didFinishLaunchingWithOptions:(NSDictionary *)launchOptions!{ ! self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; ! // Override point for customization after application launch.! rootViewController = [[GTViewController alloc] initWithNibName:nil bundle:nil]; ! [self.window setRootViewController:rootViewController]; ! ! self.window.backgroundColor = [UIColor whiteColor]; ! [self.window makeKeyAndVisible]; ! return YES; !}

Page 103: iOS Programming Intro

Add Core Location Framework Go to Targets > GPSTracker > Frameworks

Page 104: iOS Programming Intro

Add Pointers for Views, CoreLocationManager and set Delegate // GTViewController.h!// GPSTracker!!#import <UIKit/UIKit.h> !#import <CoreLocation/CoreLocation.h> !

@interface GTViewController : UIViewController! <CLLocationManagerDelegate,UITextFieldDelegate> !{ ! UIButton *startStopButton; ! UILabel *latLabel; ! UILabel *lonLabel; ! UITextField *latField; ! UITextField *lonField; ! CLLocationManager *locationManager; ! BOOL isUpdating; !} !

@end

Page 105: iOS Programming Intro

Create Objects in Root View Controller Implementation -(id)initWithNibName:(NSString *)nibNameOrNil!

"bundle:(NSBundle *)nibBundleOrNil { ! self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; ! if (self) { ! latLabel = [[UILabel alloc] initWithFrame:CGRectZero]; ! lonLabel = [[UILabel alloc] initWithFrame:CGRectZero]; ! latField = [[UITextField alloc] initWithFrame:CGRectZero]; ! lonField = [[UITextField alloc] initWithFrame:CGRectZero]; ! startStopButton = [UIButton buttonWithType:UIButtonTypeCustom]; ! [startStopButton setFrame:CGRectZero]; ! [startStopButton addTarget:self action:@selector(startStop:) ! forControlEvents:UIControlEventTouchDown]; ! [[self view] addSubview:latLabel]; ! [[self view] addSubview:lonLabel]; ! [[self view] addSubview:latField]; ! [[self view] addSubview:lonField]; ! [[self view] addSubview:startStopButton]; ! locationManager = [[CLLocationManager alloc] init]; ! [locationManager setDelegate:self]; ! [self createFrames]; ! isUpdating=NO; ! [self startStop:nil]; //use to set the first start/stop title! } ! return self; !}

Page 106: iOS Programming Intro

Add Some Style Stuff /* !Put this in init method !Note: text fields are used for values instead of labels !

"to allow cut and paste, but I really just wanted !"to have a couple of view examples here !

*/ ![[self view] setBackgroundColor:[UIColor lightGrayColor]]; ![latLabel setBackgroundColor:[UIColor clearColor]]; ![latLabel setTextAlignment:NSTextAlignmentCenter]; ![latField setBackgroundColor:[UIColor whiteColor]]; ![latField setTextAlignment:NSTextAlignmentCenter]; ![lonLabel setBackgroundColor:[UIColor clearColor]]; ![lonLabel setTextAlignment:NSTextAlignmentCenter]; ![lonField setBackgroundColor:[UIColor whiteColor]]; ![lonField setTextAlignment:NSTextAlignmentCenter]; ![latLabel setText:@"Latitude"]; ![lonLabel setText:@"Longitude"]; !

Page 107: iOS Programming Intro

Add a UITextFieldDelegate //Get rid of the editing view on the UITextFields!//so the keyboard doesn’t appear and set the !//delegate to the view controller![latField setDelegate:self]; ![lonField setDelegate:self]; ![latField setInputView:[[UIView alloc] init]]; ![lonField setInputView:[[UIView alloc] init]]; !!//Add a delegate function to prevent editing!-(BOOL)textField:(UITextField *)textField!

"shouldChangeCharactersInRange:(NSRange)range !"replacementString:(NSString *)string{ !

return NO; !}

Page 108: iOS Programming Intro

Add the Start/Stop Method -(void)startStop:(id)sender !{ ! if (!isUpdating && sender) { ! [locationManager startUpdatingLocation]; ! [latField setText:@""]; ! [lonField setText:@""]; ! [startStopButton setTitle:@"Stop”!

" "forState:UIControlStateNormal]; ! isUpdating=YES; ! } ! else { ! [locationManager stopUpdatingLocation]; ! [latField setText:@"Stopped"]; ! [lonField setText:@"Stopped"]; ! [startStopButton setTitle:@"Start”!

" "forState:UIControlStateNormal]; ! isUpdating=NO; ! } !}

Page 109: iOS Programming Intro

Add A Function To Set Frames -(void)createFrames!{ ! CGRect vF = [[self view] frame]; ! CGFloat fontHeight = [[latLabel font] pointSize]; ! ! CGRect latLabelFrame=vF; ! latLabelFrame.size.width/=2; ! latLabelFrame.size.height=fontHeight+5; ! latLabelFrame.origin.x=(vF.size.width-latLabelFrame.size.width)/2; ! latLabelFrame.origin.y= !

"(vF.size.height-(latLabelFrame.size.height+5)*5)/2; ! [latLabel setFrame:latLabelFrame]; ! ! CGRect latFieldFrame = latLabelFrame; ! latFieldFrame.origin.y+=fontHeight+5; ! [latField setFrame:latFieldFrame]; ! ! CGRect lonLabelFrame = latFieldFrame; ! lonLabelFrame.origin.y+=fontHeight+5; ! [lonLabel setFrame:lonLabelFrame]; ! ! CGRect lonFieldFrame = lonLabelFrame; ! lonFieldFrame.origin.y+=fontHeight+5; ! [lonField setFrame:lonFieldFrame]; ! ! CGRect buttonFrame = lonFieldFrame; ! buttonFrame.origin.y+=fontHeight+10; ! buttonFrame.size.height+=5; ! [startStopButton setFrame:buttonFrame]; !}

Start with application frame or view frame

Lay out everything else relative to each other (this is my own personal style, might not be for everyone)

Page 110: iOS Programming Intro

Add CLLocationManagerDelegate Methods -(void)locationManager:(CLLocationManager *)manager ! didUpdateToLocation:(CLLocation *)newLocation! fromLocation:(CLLocation *)oldLocation { ! CLLocationCoordinate2D coord = newLocation.coordinate; ! [latField setText:[NSString!

"stringWithFormat:@"%f",coord.latitude]]; ! [lonField setText:[NSString!

"stringWithFormat:@"%f",coord.longitude]]; ! NSLog(@"Updated Location To %f, %f", !

"coord.longitude,coord.longitude); !} !

-(void)locationManager:(CLLocationManager *)manager ! didFailWithError:(NSError *)error { !

"//this is usually called when someone!"//doesn’t allow app to access location!

[latField setText:@"Error"]; ! [lonField setText:[error description]]; !}

Use like printf in C

Page 111: iOS Programming Intro

Simulate a Location • Go to Debug > Location in the Simulator • Set a Custom Location

Page 112: iOS Programming Intro

Run The App

•  Note – the location won’t update in the simulator. Run the app on a phone to see the location change as you move or if the accuracy changes.