IOS
From Supernifty
iPhone, XCode and OSX Development
Contents |
Problem: Base SDK Missing
- Project->Edit Project Settings - set Base SDK to Latest iOS.
- Project->Edit Active Target - set Base SDK to Latest iOS.
- Restart XCode
Native app with HTML UI
- Use a UIWebView as a container for the HTML
Local Resources
- (void)loadView {
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSData *data = [NSData dataWithContentsOfFile:path];
[webView loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:[NSURL fileURLWithPath:path]];
}
- Setting the baseURL ensures other resources will also be loaded when the main HTML file loads in the webview.
- Use an absolute URL to load remote URL.
Performance Tips
- Use a single UIWebView
- Build new views off screen and animate them in - see Dashcode for examples
- If a Low Memory Notification is received, null JavaScript objects, and reinitialize them.
Authentication
- No UI required: use https://username:password@www.site.com
- To present a UI:
- use a separate URL connection
- connection:didReceiveAuthenticationChallenge
- Store credentials with NSURLCredentialPersistenceForSession
- UIWebView will use cached credentials
Executing JS from Objective-C
[webView stringByEvaluatingJavaScriptFromString:@"my_js()"];
- JS should be in a separate file
- JS should be copied, not compiled
- Ensure the view has loaded (use webViewDidFinishLoad)
Executing Objective-C from JS
- JS sets the location to a custom URL
native
function go_native() {
window.location = "http://myapp/go_native";
}
- Capture the load event
- (BOOL)webView:(UIWebView *)view shouldStartLoadWithRequest:(NSURLRequest *)req {
if ( [[[req URL] host] isEqualToString:@"myapp"]) {
NSString *cmd = [[[req URL] path] lastPathComponent];
if ([cmd isEqualToString:@"go_native""]) {
// do native stuff
}
return NO;
}
}
Optimization
Reduce Image Count
- Once an image is decoded it uses a lot of memory
- Generate images in CSS
CSS Gradients
background: -webkit-gradient ( linear, left top, left 45%, from (#c3f7a5), to(white) );
means: type of gradient (linear/radial), start, end, colour start, colour end.
- visit http://westciv.com/tools/gradients/ to build
CSS Masks
-webkit-mask
analagous to background properties
e.g.
-webkit-mask-box-image: url(circle-mask.png) 100 75;
Instead of using circle-mask.png, a radial gradient or SVG image ( <circle...>) could be used, to eliminate that image.
CSS Reflections
-webkit-box-reflect <direction> <offset> <mask-box-image>
e.g.
-webkit-box-reflect below 5px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop( 0.7, transparent ), to(white));
CSS Transforms
- translate, rotate, stretch or skew
e.g.
.item {
-webkit-transform: rotate(180deg) scale(2.5) translateX(100px);
}
Also 3d transformations.
See http://developer.apple.com/safari - Poster Circle and Finger Tips for examples.
CSS Transitions
.item {
-webkit-transform: scale(1) rotate(0deg);
opacity: 0;
-webkit-transition-property: -webkit-transform, opacity;
-webkit-transition-duration: 1.3s, 2s;
}
.move {
-webkit-transform: scale(1.25) rotate(180deg);
opacity: 1;
}
function move(o) {
o.className = ( o.className == "item" ) ? "item move" : "item";
}
- Modify the linearity of the transition with -webkit-transition-timing-function
- Delay the transition with -webkit-transition-delay
CSS Animations
- Define the animation
@-webkit-keyframes 'fall' {
from { -webkit-transform: translateY( -50px ); } /* start from above top */
to { -webkit-transform: translateY( 600px ); } /* finish below bottom */
}
- Add transformation
@-webkit-keyframes 'fade' {
0% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 0; }
}
- Apply to item
.leaf {
-webkit-animation-name: 'fall', 'fade';
-webkit-animation-duration: 10s, 10s;
-webkit-animation-iteration-count: infinite, infinite;
-webkit-animation-timing-function: linear, ease-in;
}
- Associated events: webkitAnimationStart, webkitAnimationIteration, webkitAnimationEnd
- CSS transitions, animations will always be faster than JavaScript equivalent.
Buttons
.button {
color: white;
background-color: #cc0000;
border: 3px solid;
border-color: black;
width: 275px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 18px;
font-family: "Helvetica-Neue";
font-weight: bold;
-webkit-border-radius: 10px; /* rounded */
-webkit-box-shadow: 0px 2px gray;
text-shadow: 0px 0px 8px black;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%,
from(rgba(255,255,255,0.5)), to(rgba(255,255,255,0.2)),
color-stop(.5,rgba(255,255,255,0.3)), color-stop(.5,rgba(255,255,255,0.0))
);
-webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; -webkit-user-select: none; }
function enable(b) {
button.style.backgroundColor = 'blue';
}
function disable(b) {
button.style.backgroundColor = 'red';
}
Caching with an HTML5 database
if ( window.openDatabase ) { // check availability
var db = openDatabase( "db", "1.0", "displayName", 250000 ); // expected size
}
- Just the name is required
db.transaction( function(tx) {
tx.executeSQL( "create table t (id integer, item text)" );
});
- webkit.org sticky notes example
Game Center
Provides
- friends
- leaderboards
- achievements
- multiplayer
Closures in iOS4 and OSX 10.6
Called "blocks" by Apple
{
int x = 2;
void (^closure)(int) = ^(int y) {
printf( "%d %d", x, y );
}
closure( 3 ); // prints "2 3"
}
- Used for a lot of GameKit calls to implement async.
Signing in
- GKLocalPlayer = the player on this device
- authenticateWithCompletionHandler
Friends
- GKPlayer = another player
- loadFriendsWithCompletionHandler
Leaderboards
- GKScore - for reporting scores
- GKLeaderboard - for querying the leaderboard
- GKLeaderboardViewController - modal view controller to display leaderboard
- First need to setup leaderboard in iTunesConnect
Achievements
- GKAchievementDescription - get available achievements
- GKAchievement - for reporting an achievement, and getting a user's achievements
- GKAchievementViewController - UI
- Setup within iTunesConnect
Similar to leaderboards.
Multiplayer
Auto Match
- GKMatchRequest - parameters of match, sent to server
- GKMatchmaker - used to make request, returns GKMatch
- GKMatchmakerViewController - view of matches
- GKMatch - provides peer-to-peer comms functionality
- GKPlayer array is returned instead of GKMatch if client-server model.
Invites
- via GKMatchmakerViewController - inviter
- uses push notifications
- GKInvite
- Invitee - implement inviteHandler, can be called at any time.
- playersToInviteHandler - for server based. Both on shared GKMatchMaker object.
Comms
- GKMatch object
- In-voice available only on peer-to-peer, with GKVoiceChat
Process: Signing and Certificates
Certificate Expired
- Generate and submit CSR with KeyChainAccess
- Download certificate
Provisioning Expired
- Modify dev and dist profiles to use the new certificate is necessary
- Download and install in keychain.
- Delete expired if necessary
Process: Ad-Hoc Build
Setup
- Duplicate Release configuration and rename Ad-Hoc
- Change to use Ad-Hoc certification
- Manage Schemes
- Configure Archive to use Ad-Hoc
Release
- Update the version
- Click on target, info; update bundle version, bundle versions string; short.
- Product->Edit Schemes. Select Archive
- Product->Archive
- Archive (.ipa)
- Include .ipa and .mobileprovision when distributing
Testing the ipa
unzip file.ipa
- look for embedded.mobileprovision to check valid devices