tag:blogger.com,1999:blog-47759283999392591882024-03-08T10:54:25.764-08:00Andy's IPhone Objective C notesandyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-4775928399939259188.post-41800844947697452602012-01-12T05:55:00.000-08:002012-01-12T06:01:41.751-08:00Graphics LibrariesDrawing stuff directly in ios gets a bit slow as soon as you have more than a few images onscreen. So we should use a library like:<br /><br /><a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial">Cocos 2d tutorial</a><br /><a href="http://www.raywenderlich.com/457/intro-to-box2d-with-cocos2d-tutorial-bouncing-balls">Cocos 2d with Box2d tutorial</a><br /><br />For the more hard core there is <a href="http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-table-of.html">Open GL</a><br /><br />For full cross platform 3D goodness at a minimum $400 price tag (plus you'd need a copy of Maya) there is the rather awesome looking: <a href="http://unity3d.com/support/resources/"> Unity </a>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-59324026800180466622012-01-03T09:04:00.000-08:002012-01-03T09:06:14.462-08:00ControllersHow to replace the current controller with a new one. In this case GameController<br /><br /><blockquote><br /> GameController *c = [[GameController alloc] initWithNibName:@"GameController" bundle:nil];<br /> [self presentModalViewController:c animated:YES];<br /> [c release];<br /></blockquote><br /><br />For a navigatable version with back functionality:<br /><br /><blockquote> [self.navigationController pushViewController:c animated:YES];<br /></blockquote>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-67625841165868164762011-11-04T10:25:00.000-07:002011-11-04T10:41:58.553-07:00App Store submissionUnlike the Android Market the Apple App Store submission is a pain in the backside. Here are my notes from repeatedly failing at it:<br /><br />Setup your app details in <a href="https://itunesconnect.apple.com/">Itunes Connect</a>. Your bundle ID should look something like this: com.nuclearcarrot.oystererrors<br /><br />Next manage your certificates and profiles at <a href="https://developer.apple.com/ios/manage/bundles">apple developer </a><br />Go to Provisioning. Create a Distribution Profile (Note a Developer Profile). Can not use a Wildcard AppId for this.<br /><br />Your appid should look like this: 1234123456.com.nuclearcarrot.oystererrors<br /><br />Download this baby and drag it into XCode. <br /><br />Xcode Project -> Build Settings -> Code Signing and configure it as Iphone Distribution.andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com2tag:blogger.com,1999:blog-4775928399939259188.post-75187065398106316082011-10-23T12:20:00.000-07:002011-11-05T07:12:48.075-07:00LinksHow to change <a href="http://stackoverflow.com/questions/4602586/i-want-to-make-uilabels-text-bold"> font </a><br /><br />Xcode <a href="http://stackoverflow.com/questions/146297/hidden-features-of-xcode">shortcuts:</a>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-31944393260434791382011-07-18T05:18:00.000-07:002011-07-18T05:22:02.178-07:00Check if Running on SimulatorHow to add an <span style="font-weight:bold;">if</span> to check if you are running on the simulator:<br /><br /><code><br />#if TARGET_IPHONE_SIMULATOR<br /> NSLog(@"APPIRATER NOTE: not supported on the iOS simulator.");<br />#else<br /> // Do Live stuff<br />#endif<br /></code><br /><br /><a href="http://stackoverflow.com/questions/458304/how-can-i-programmatically-determine-if-my-app-is-running-in-the-iphone-simulator">Source</a>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com1tag:blogger.com,1999:blog-4775928399939259188.post-84032294656604242011-06-05T04:31:00.000-07:002011-06-05T04:37:58.661-07:00Core Data schema change migrationPlace the below in your:<br /><code><br />- (NSPersistentStoreCoordinator *)persistentStoreCoordinator<br />method<br /></code><br /><br />To remove the old data store (clear out old data models):<br /><br /><code> [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];<br /></code><br /><br />To migrate data using <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmLightweight.html#//apple_ref/doc/uid/TP40008426-SW1">Lightweight Migration </a><br /><br /><code><br /> [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];<br /></code><br /><br />In Xcode 4 we migrate data models by:<br />select data model. (on left)<br />Apple - alt - 1 ( View - Utilities - File Inspector)<br />Versioned Data model (on right side of utilities window)andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-87797746538861075922011-05-11T12:12:00.000-07:002011-05-11T12:14:36.144-07:00Camera + Action Sheets BasicsHeader should implement:<br /><code><br />@interface CapturedPhotoController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIActionSheetDelegate> {<br /></code><br /><br />and then we paste these methods into the main file:<br /><br /><code><br /><br />- (IBAction) takePictureButton: (id) sender {<br /> NSLog(@"snap");<br /> <br /> if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {<br /> NSLog(@"is camera ok");<br /> UIActionSheet *photoSourceSheet = [[UIActionSheet alloc] initWithTitle:@"Select fugitive picture"<br /> delegate:self <br /> cancelButtonTitle:@"cancel" <br /> destructiveButtonTitle:nil<br /> otherButtonTitles:@"Take new photo", @"Choose existing photo", nil, nil];<br /> <br /> [photoSourceSheet showInView:self.view];<br /> [photoSourceSheet release];<br /> }<br /> else {<br /> NSLog(@"No camera");<br /> UIImagePickerController* picker = [[UIImagePickerController alloc] init];<br /> picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;<br /> picker.delegate = self;<br /> picker.allowsEditing = YES;<br /> [self presentModalViewController:picker animated:YES];<br /> }<br />}<br /><br />-(void) actionSheet:(UIActionSheet *) actionShet didDismissWithButtonIndex:(NSInteger)buttonIndex {<br /> UIImagePickerController *picker = [[UIImagePickerController alloc] init];<br /> picker.delegate = self;<br /> picker.allowsEditing = YES;<br /> <br /> switch(buttonIndex) {<br /> case 0:<br /> NSLog(@"user wants to take new picture");<br /> picker.sourceType = UIImagePickerControllerSourceTypeCamera;<br /> picker.delegate = self;<br /> picker.allowsEditing= YES;<br /> break;<br /> case 1:<br /> NSLog(@"user wants to choose existing picture");<br /> picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;<br /> break;<br /> default:<br /> [picker release];<br /> return;<br /> }<br /> [self presentModalViewController:picker animated:YES];<br /><br />}<br /><br />-(void) imagePickerController:(UIImagePickerController *) picker<br /> didFinishPickingImage:(UIImage*) image<br /> editingInfo:(NSDictionary*) editingInfo {<br /> self.fugitive.image = UIImagePNGRepresentation(image);<br /> [self dismissModalViewControllerAnimated:YES];<br /> [picker release];<br />}<br /><br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com1tag:blogger.com,1999:blog-4775928399939259188.post-19874733470404643582011-05-11T12:08:00.000-07:002011-05-11T12:15:41.913-07:00location managerCode samples for using the iPhone location API.<br /><br />in the header:<br /><br /><code><br />#import CoreLocation/CoreLocation.h<br />@interface FugitiveDetailViewController : UIViewController<CLLocationManagerDelegate> {<br /><br /></code><br /><br />in the main:<br /><br /><code><br /><br />- (void)viewWillAppear:(BOOL)animated {<br /><br /> self.locationManager=[[CLLocationManager alloc] init];<br /> self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;<br /> self.locationManager.delegate = self;<br /> [self.locationManager startUpdatingLocation];<br />}<br /><br />// Implement these 2 methods:<br />-(void) locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*) oldLocation {<br /> NSLog(@"Core location has position!");<br /> capturedToggle.enabled=YES;<br />}<br />-(void) locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error {<br /> NSLog(@"Core location has NO position :-(");<br /> capturedToggle.enabled=NO;<br />}<br /><br />//to read location:<br />CLLocation *curPos = self.locationManager.location;<br />latitude = [NSNumber numberWithDouble:curPos.coordinate.latitude];<br />longitude = [NSNumber numberWithDouble:curPos.coordinate.longitude];<br /><br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-46839525955158384252011-05-04T13:53:00.000-07:002011-05-04T13:56:01.207-07:00Sample transition code<span style="font-weight:bold;">For a 'horizontal flip' style transition:</span><br /><code><br /> CapturedPhotoController *cont = [[CapturedPhotoController alloc] initWithNibName:@"CapturedPhotoController" bundle:nil];<br /> cont.fugitive = fugitive;<br /> cont.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;<br /><br /> [self.navigationController presentModalViewController:cont animated:YES];<br /> [cont release];<br /><br /></code><br /><br /><span style="font-weight:bold;">Normal transition with 'back' button on top:</span><br /><code><br /> FugitiveDetailViewController *fugitiveDetailViewController = [[FugitiveDetailViewController alloc] initWithNibName:@"FugitiveDetailViewController" bundle:nil];<br /> fugitiveDetailViewController.fugitive = [self.resultsController objectAtIndexPath:indexPath];<br /> [self.navigationController pushViewController:fugitiveDetailViewController animated:YES];<br /> [fugitiveDetailViewController release];<br /><br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-71204114845479910422011-05-01T03:20:00.000-07:002011-05-01T03:27:58.019-07:00Loading data from SQLite and populating a table<span style="font-weight:bold;">Loading data:</span><br /><code><br /><br />- (void)viewWillAppear:(BOOL)animated {<br /> [super viewWillAppear:animated];<br /> <br /> if (self.resultsController != nil) {<br /> return;<br /> }<br /> <br /> iBountyHunterAppDelegate *appDelegate = (iBountyHunterAppDelegate *)[[UIApplication sharedApplication] delegate];<br /> NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;<br /> <br /> NSFetchRequest *request = [[NSFetchRequest alloc] init];<br /> NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Fugitive" inManagedObjectContext:managedObjectContext];<br /> [request setEntity:entityDescription];<br /> NSPredicate *predicate = [NSPredicate predicateWithFormat:@"captured == YES"];<br /> [request setPredicate:predicate];<br /> NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];<br /> NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];<br /> [request setSortDescriptors:sortDescriptors];<br /> [sortDescriptors release];<br /> [sortDescriptor release];<br /> <br /> NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request<br /> managedObjectContext:managedObjectContext sectionNameKeyPath:nil<br /> cacheName:@"captured_list.cache"];<br /> fetchedResultsController.delegate = self;<br /> <br /> NSError *error;<br /> BOOL success = [fetchedResultsController performFetch:&error];<br /> if (!success) {<br /> // Handle error<br /> }<br /> <br /> self.resultsController = fetchedResultsController;<br /> [request release];<br /> <br /> [self.tableView reloadData];<br />}<br /><br /></code><br /><br /><span style="font-weight:bold;">Force a reload on data change: V useful:</span><br /><br /><code><br />-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {<br /> [self.tableView reloadData];<br />}<br /></code><br /><br /><span style="font-weight:bold;">...and the code to display the data in the table:</span><br /><br /><code><br />// Number of selections allowed:<br />- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {<br /> return [[self.resultsController sections] count];<br />}<br /><br /><br />// Number of rows in the table view.<br />- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {<br /> return [[[self.resultsController sections] objectAtIndex:section] numberOfObjects];<br />}<br /><br /><br />// Customize the appearance of table view cells.<br />- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {<br /> <br /> static NSString *CellIdentifier = @"Cell";<br /> <br /> UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];<br /> if (cell == nil) {<br /> cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];<br /> }<br /> <br /> // Set up the cell...<br /> Fugitive *fugitive = [self.resultsController objectAtIndexPath:indexPath];<br /> cell.textLabel.text = fugitive.name;<br /> return cell;<br />}<br /><br /><br />- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />// Delegate a click down to this class:<br /> FugitiveDetailViewController *fugitiveDetailViewController = [[FugitiveDetailViewController alloc] initWithNibName:@"FugitiveDetailViewController" bundle:nil];<br /> fugitiveDetailViewController.fugitive = [self.resultsController objectAtIndexPath:indexPath];<br /> [self.navigationController pushViewController:fugitiveDetailViewController animated:YES];<br /> [fugitiveDetailViewController release];<br />}<br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-76973948416107789542011-04-11T14:29:00.001-07:002011-04-11T14:33:11.659-07:00Core data basicsSo core data. Turns out I actually like this bit of IPhone coding. It makes ORM / DB stuff really easy.<br /><br />Samble code to load and sort a 'fugitive' object from an SQLLite DB<br /><br /><code><br /><br />- (void)viewWillAppear:(BOOL)animated {<br /> [super viewWillAppear:animated];<br /> bountyHunterAppDelegate *appDelegate = (bountyHunterAppDelegate*)[[UIApplicaion sharedApplication] delgate];<br /> NSManagedObjectContext *managedObectContext = appDelegate.managedObjectContext;<br /> // Create request object to get data<br /> NSFetchRequest *request = [[NSFetchRequest alloc] init];<br /> NSEntityDescription *entity = [NSEntityDescription entityForName:@"Fugitive" inManagedObjectContext:managedObectContext];<br /> [request setEntity:entity];<br /> <br /> NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];<br /> NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor];<br /> [request setSortDescriptors:sortDescriptors];<br /> [sortDescriptor release];<br /> [sortDescriptors release];<br /> <br /> NSError *error;<br /> NSMutableArray *mutablesFetchResults = [[managedObectContext executeFetchRequest:request error:&error] mutableCopy];<br /> if (mutablesFetchResults == Nil) {<br /> NSLog(@"all buggered");<br /> }<br /> self.items = mutableCopy;<br /> [mutablesFetchResults release];<br /> [request release];<br />}<br /><br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-80285472001883681322011-04-04T11:40:00.000-07:002011-11-05T11:19:07.652-07:00XCode tips<a href="http://stackoverflow.com/questions/146297/what-are-those-little-xcode-tips-tricks-you-wish-you-knew-about-2-years-ago">Top XCode tips</a><br /><br />CTRL-APPLE-B = Analyze Build - report memory leaks.<br />Profile Build - Profiler<br /><br />CTRL-APPLE-UP = swap between .h and .c filesandyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-73780740891427767172011-03-28T13:52:00.000-07:002011-03-28T13:58:41.108-07:00NSNotificationCenter / Events / ObserverAdds an observer for the UI Keyboard appearing. - When it does it calls the method: keyboardDidShow<br /><br /><code><br />- (void) viewWillAppear:(BOOL)animated {<br /> [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:)<br /> name:UIKeyboardDidShowNotification object:nil];<br />}<br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-70250155767235931422011-03-28T13:42:00.000-07:002011-03-28T13:49:17.903-07:00Sorting ArraysSorting a NSMutableArray of maps by the value contained in "name_key_of_map"<br /><br /><code><br /> NSSortDescriptor *nameSorter = [[NSSortDescriptor alloc] initWithKey:"name_key_of_map" ascending:YES selector:@selector(caseInsensitiveCompare:)];<br /> <br /> [drinks sortUsingDescriptors:[NSArray arrayWithObject:nameSorter]];<br /> [nameSorter release];<br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-77489083749698179832011-03-21T13:31:00.001-07:002011-07-18T09:50:05.284-07:00Logging & StringsNote: Different Log commands are required for Strings to ints.<br />Logging:<br /><br /><code><br /> NSLog(@"%d", some_int );<br /> NSLog(@"%f", some_double );<br /> NSLog(@"%lld", some_long );<br /> NSLog(@"%@", string_variable);<br /><br />NSString* myNewString = [NSString stringWithFormat:@"%d", myInt];<br /> double d = [myNewString doubleValue];<br /> long long l = [myNewString longLongValue]; //long long = 64 bit<br /><br /></code><br /><a href="http://stackoverflow.com/questions/169925/how-to-do-string-conversions-in-objective-c">string conversions</a><br /><br />Another cool logging trick - this prints the function name and line etc:<br /><code><br />NSLog(@"%s %d %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);<br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-8177273192261456262011-03-16T13:27:00.002-07:002011-03-17T14:03:39.869-07:00Basic CollectionsSample List and Map:<br /><br /><code><br />(header file)<br /><br />interface RootViewController : UITableViewController {<br /> NSMutableArray* drinks;<br /> NSDictionary* drinkMap;<br />}<br />@property(nonatomic, retain) NSMutableArray* drinks;<br />@property(nonatomic, retain) NSDictionary* drinkMap;<br /><br /></code><br /><br />.... and initing the array:<br /><br /><code><br /><br /> // Load directly<br /> drinks = [[ NSMutableArray alloc] initWithObjects: @"Mojito", @"Long Island Iced Tea", @"Firecracker", nil];<br /><br /> // Load from a resource (prefered - its all about the plists).<br /> NSString *path = [[NSBundle mainBundle] pathForResource: @"DrinkDirections" ofType: @"plist"];<br /> <br /> drinks = [[ NSMutableArray alloc] initWithContentsOfFile:path];<br /> <br />// Note well: If you are initing a big plist dictionary then load it in as an Array and once you have an element that bit is a Dictionary.<br /><br /></code>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-41367203102265144492011-03-07T13:10:00.000-08:002011-07-18T09:55:19.849-07:00methods + properties<code><br />@synthesize bob<br /></code><br />Auto generates Getters and Setters for 'bob'<br /><hr/><br /><br /><code><br /> notesField.text= @"new value";<br /></code><br />This is how you set a property.<br /><br /><hr/><br /><code><br /> [sender setTitle:@"i've been clicked!!" forState:UIControlStateNormal];<br /></code><br />This is how you call a method - The Apple term is 'selector' when used it becomes a 'message'. We use the notation:<br /><code><br />[object argument1:value argument2:value]<br /></code><br />Note that argument1 replaces / is the method nameandyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0tag:blogger.com,1999:blog-4775928399939259188.post-4620000348500229332011-03-06T06:04:00.000-08:002011-07-18T10:22:47.524-07:00Reference Counting & PropertiesI have 1 word for this shit - Yuck.<br /><br />A quick summary of properties:<br /><br /><br /><span style="font-style:italic;">@property (nonatomic, <span style="font-weight:bold;">readonly</span>) int* me<br /></span><br />creates a getter: object.me<br /><br /><span style="font-style:italic;">@property (nonatomic, <span style="font-weight:bold;">readwrite</span>) int* me<br /></span><br />creates a getter + setter (DEFAULT)<br /><br /><hr/><br /><br /><span style="font-style:italic;">@property (nonatomic, <span style="font-weight:bold;">assign</span>) NSString* myStr<br /></span><br />'Normal' assign - does not increase reference count. (DEFAULT)<br /><br /><span style="font-style:italic;">@property (nonatomic, <span style="font-weight:bold;">retain</span>) NSString* myStr<br /></span><br />as above but increases the reference count by 1. (Retains the String - dont release this I'm using it!).<br /><br /><span style="font-style:italic;">@property (nonatomic, <span style="font-weight:bold;">copy</span>) NSString* myStr<br /></span><br />clone.<br /><br />For Primitives use <span style="font-weight:bold;">retain</span>.<br />For Objects that may change & Strings use <span style="font-weight:bold;">copy</span> <br /><br /><hr/><br /><br />Style: <span style="font-weight:bold;">Only release the object if you created it</span>. Objects returned from methods should be using <span style="font-weight:bold;">autorelease</span> this means you do not have to worry about cleaning up the object when you have finished with it. <br /><br /><br /><a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1">Further reading</a>andyhttp://www.blogger.com/profile/08921286377175955589noreply@blogger.com0