Christina Moulton, Teak Mobile Inc.
Christina Moulton
Freelance iOS dev
Suffered through crappy syntax you won't need to bother with
How to create basic native iOS apps from scratch without wasting a ton of time trying to work against the tools and the language.
Issues that stop people from learning iOS development on their own
Game programming
Everything
App Store revenues: $5B im 2012
Employment & contract opportunities
Something different
Getting to know you: Why? What's your background?
Speed
Ease of UI development & hardware integration
Richer UX
Earlier access to all device features
Easier persistence and offline operation
More later (time permitting)
Syntax
Design patterns
Interface Builder
Apple's web-based tools
Session 1: Design Patterns & Obj-C Features, Apple's Tools, SDK & Core Classes
Exercise 1: Interface Builder, IBOutlets & IBActions
Exercise 2: Tableviews, datasources & delegates
Lunch
Session 2: iOS App Ecosystem, 3rd Party Tools & Testing, Key Resources
(Storyboards & UI Components)
Exercise 3: JSON REST APIs & Storyboards
Session 3: Code Signing, App Store Submission, What Should Be a Native App vs. Web App
Time permitting: In App Purchase, Autolayout
Objective-C + SDK
UI: Direct Manipulation & Multi-Touch
Just released iOS 7
Class Header (.h)
#import "AnyOtherHeaderFile.h"
@interface MyClass : SuperClass {
// declare instance variables
// (optional)
NSInteger _myInteger;
}
// define properties
@property (nonatomic, strong) NSString *myString;
// define methods
- (anytype)doIt;
- (anytype)doItWithA:(anytype)a;
- (anytype)doItWithA:(anytype)a andB:(anytype)b;
+ (anytype)classDoIt;
@end
Class Implementation (.m)
#import "MyClass.h"
@implementation MyClass
// implement methods (including custom inits)
- (id)init
{
self = [super init];
if (self) { // initialize ivars
}
return self;
}
- (anytype)doItWithA:(anytype)a andB:(anytype)b;
{
NSLog(@"Doing it with %@ and %@", a, b);
return a;
}
@end
Messaging:
[receiver message];
[receiver messageWithParameter:aParameter];
Create an Instance of a Class & Call Methods
MyClass *myObject = [[MyClass alloc] init];
[myObject doIt];
id returnValue = [myObject doItWithA:anA andB:aB];
[MyClass classDoIt];
anyType myVariable;
NSInteger anInteger;
NSObject *anObject;
id anotherObject;
Common Types
int (NSInteger), float, double
BOOL: YES, NO, TRUE, FALSE
ClassName *: e.g., NSString *, NSArray *
id: Ref to any object (NSObject * or subclass)
myObject.myString = @"a String"; [myObject setMyString:@"a String"]; aString = myObject.myString; aString = [myObject myString];
Compile-time autosynthesis since Xcode 4.4
Qualifiers in declaration
@property (nonatomic, strong) aType aProperty;
ARC: strong, weak
Primitives: assign, copy
Threading: nonatomic, atomic
Accessors: readwrite, readonly
NSString *catOne = @"Mittens";
NSString *catTwo = @"Mr. Bigglesworth";
NSString *statement = [NSString stringWithFormat:
@"The cats to be worshipped are %@ and %@",
catOne, catTwo];
NSLog(@"%@", statement);
NSString *tipString = @"24.99";
float tipFloat = [tipString floatValue];
Also NSMutableString
NSMutableArray *array = [NSMutableArray arrayWithObjects:
catOne, catTwo, nil];
[array addObject:@"Sylvester"];
NSString *sylvester = [array objectAtIndex:2];
NSLog(@"That cat's name is: %@", sylvester);
NSLog(@"%d cats!", array.count);
for (NSString *cat in array) {
NSLog(@"Cat: %@", cat);
}
// Xcode 4.4+ alt: array[2]
NSArray *anArray = @[@"John", @"Jane", "Waldo"];
NSString *waldo = anArray[2];
Also NSMutableArray, NSSet, NSDictionary
Encapsulated chunks of code
int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
NSLog(@"%d", myBlock(3)); // prints 21
multiplier = 8;
NSLog(@"%d", myBlock(3)); // still prints 21
[UIView animateWithDuration:2.0
animations:^ {
self.view.alpha = 1.0;
self.view.frame = CGRectMake(0, 0, 72, 96);
}
];
MVC
Singleton
Protocol & Delegate
Decorator: Category
Observer
Model: Data Model Objects
View: UIView & subclasses
Controller: UIViewController & subclasses
Model <-> Controller <-> View
Seldom code views
(E.g., UITableView)
AppDelegate, NSUserDefaults, NSFileManager
Common for resources: Reachability, Location Services, Logging, ...
Thread-safe access
+ (MySingleton *)sharedInstance
{
static dispatch_once_t once;
static MySingleton * sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Common in UIKit classes, e.g., UITableView Datasource & Delegate
Datasource is a specific type of delegate
Configuration & composition over inheritance
@protocol InfoDelegate
- (void)showAppShareView;
- (void)restartTour;
@optional
- (void)optionalMethod;
@end
@interface InfoViewController: UIViewController
@property (nonatomic, strong) id<InfoDelegate> delegate;
@end
Extend a class with additional methods
Included at compile time
@interface ClassToAddMethodsTo (category)
// ...methods go here
@end
@interface NSString (MD5)
- (NSString *)MD5Hash;
@end
No new ivars
KVO: Key-Value Observing
Controller can observe Model for changes
Register for notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
- (void)keyboardDidShow:(NSNotification *)aNotification
{
// ...
}
The old way: Reference Counting
Need it?
[anObject retain];
Done with it?
[anObject release];
Dealloc'd when release count reaches 0
Return it without retaining it, but don't dealloc until caller is done with it
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
- (void)someOtherMethod {
id instance = [obj myMethod];
// not dealloc'd until after this method returns
}
Retain/release calls inserted by compiler
No reason not to use (iOS 5.0+)
Qualifiers:
Strong: Owns it
Weak: Non-owning reference (e.g., to parent). Set to nil when no strong references to object exist
Unsafe unretained: Non-owning reference. Not set to nil (dangling pointers)
Autoreleasing: Passed by reference and autoreleased on return
Consider object graph: Leaks if retain cycles
@interface ClassA
@property (nonatomic, strong) ClassB *objectB;
@end
@interface ClassB
@property (nonatomic, strong) ClassA *objectA;
@end
@interface ClassA
@property (nonatomic, strong) ClassB *objectB;
@end
@interface ClassB
@property (nonatomic, weak) ClassA *objectA;
@end
Xcode windows
Project settings & .plist
main.m
-Prefix.pch
AppDelegate
.xib
.storyboard
.xcassets
Tests
Live Demo
Simulator: Hardware
@property (nonatomic, weak) IBOutlet UIButton *myButton;
- (IBAction)myAction:(id)sender;
Create a project with a button and a label
Add an integer property or ivar to track counts
Tapping on the button should change the label text (label.text) to display the number of times the button has been pressed
([NSString stringWithFormat:@"Taps: %d", self.tapCount])
Challenges:
Add a clear count button to restart
Change to a shake or swipe gesture counter
@property (nonatomic, weak) IBOutlet UIButton *counterButton;
@property (nonatomic, weak) IBOutlet UILabel *counterLabel;
@property (nonatomic) NSInteger tapCount;
- (IBAction)incrementAndUpdateCount:(id)sender
{
self.tapCount++;
self.counterLabel.text = [NSString stringWithFormat:@"Taps: %d",
self.tapCount];
}
Keyboard & input views
Multitasking
Social media & Sharing
In-App purchase
Game center
Notifications: Push & local
iAd
AirPrint
Location Services
Sound
Accessibility
Edit menu
Undo: buttons & shaking
iCloud
Passbook
Christina Moulton, Teak Mobile Inc.