The iOS Dev Diary

The iOS Dev Diary

By Jay VersluisTechnology
Download on the App Store

The iOS Dev Diary episodes

  • How to use Popovers on iPad – Part 2: Storyboard

    In this series I’ll show you how to create Popovers on iPad. They’re fairly easy to create once you get the hang of the inner workings of the UIPopoverController.

    I’ll show you how to create basic Popover in code and in your Storyboard, and we’ll discuss how you can retrieve data from a Popover when it’s dismissed. We’ll do this with a simple UIDatePicker. In the last video I’ll demonstrate how you can pick images from the camera roll using the UImagePickerController with a Popover – which is how you’re meant to do it on iPad.

    The series contains three videos in total:

    • Part 1 deals with the initial code and class etup
    • Part 2 deals with setting up the UIStoryboard and connect our code to it
    • and in Part 3 we’ll implement a UIImagePickerController to demonstrate a use case
    • Enjoy!

      Get the code for this project on GitHub
      • https://github.com/versluis/Popovers
      • 10 min
      • How to use Popovers on iPad – Part 1: Code

        In this series I’ll show you how to create Popovers on iPad. They’re fairly easy to create once you get the hang of the inner workings of the UIPopoverController.

        I’ll show you how to create basic Popover in code and in your Storyboard, and we’ll discuss how you can retrieve data from a Popover when it’s dismissed. We’ll do this with a simple UIDatePicker. In the last video I’ll demonstrate how you can pick images from the camera roll using the UImagePickerController with a Popover – which is how you’re meant to do it on iPad.

        The series contains three videos in total:

        • Part 1 deals with the initial code and class etup
        • Part 2 deals with setting up the UIStoryboard and connect our code to it
        • and in Part 3 we’ll implement a UIImagePickerController to demonstrate a use case
        • Enjoy!

          Get the code for this project on GitHub
          • https://github.com/versluis/Popovers
          • Watch the full course in one convenient playlist:
            Catch this episode on my iOS Dev Diary Podcast:

            22 min
          • How to convert your iPhone Storyboard into an iPad Storyboard

            Sometimes it’s just easier to start from an existing Storyboard rather than build everything again from scratch. Especially so when you want to create an iPad version of your iPhone app.

            When you change your deployment info to Universal, Xcode even offers to copy your existing storyboard for you. That’s really nice – but even though it behaves like an iPad storyboard, when you open it in Interface Builder it still looks like you’re creating an iPhone layout. This makes re-arranging things difficult.

            Help it at hand with a simple tweak. Under the hood, a Storyboard is just an XML file and as such as a plethora of key/value pairs we can change by hand.

            First, make sure you display your layouts in “3.5inch” mode. You can do that by clicking that little icon at the bottom of Interface Builder:

            Next head over to the File Inspector and right-click your storyboard, then select “Open as Source Code”. This will display all that XML code.

            In the second line of the document you’ll find a very long line – somewhere in it you’ll find something like this:

            targetRuntime="iOS.CocoaTouch"

            Simply change that line to

            targetRuntime="iOS.CocoaTouch.iPad"

            This will make Interface Builder display your storyboard with iPad characteristics. All we now have to do is to make it look like a Storyboard again rather than XML code – so head back and right-click on the file again, then select “Open as Interface Builder – iOS Storyboard”.

            • http://stackoverflow.com/questions/8465769/converting-storyboard-from-iphone-to-ipad
            • Watch the full course in one convenient playlist:
              Catch this episode on my iOS Dev Diary Podcast:

              9 min
            • iCloud in your iOS Apps – Part 5: Initial Import Hack

              In this final part of the series I’ll let you in on a little secret that will help our app synchronise iCloud Core Data for the first time when it’s installed on another device.

              Some devices it appears don’t display existing iCloud results upon first launch. To remedy this, I’ll show you how to re-fetch the Fetched Results Controller in your sample app.

              Watch the whole series
              • Part 1 is about Setup and Prep Work
              • Part 2 is about using Key/Value Storage
              • Part 3 is about using Document Storage
              • Part 4 is about using Core Data with iCloud
              • and Part 5 is about the initial import into the Core Data store
              • Enjoy!

                Watch the full course in one convenient playlist:
                Catch this episode on my iOS Dev Diary Podcast:

                8 min
              • iCloud in your iOS Apps – Part 4: iCloud and Core Data

                In this part we’ll talk about how to make your Core Data powered app work with iCloud. This involves adding an option to your persistent store coordinator which will allow Core Data to write log files to iCloud. When changes are detected, the local Core Data store can merge them using those log files.

                Here are the iCloud methods I added to the MasterViewController. First the observers under viewDidLoad:

                - (void)viewDidLoad
                {
                [super viewDidLoad];
                self.navigationItem.leftBarButtonItem = self.editButtonItem;
                UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
                self.navigationItem.rightBarButtonItem = addButton;
                // add iCloud observers
                [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(storesWillChange) name:NSPersistentStoreCoordinatorStoresWillChangeNotification object:self.managedObjectContext.persistentStoreCoordinator];
                [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(storesDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:self.managedObjectContext.persistentStoreCoordinator];
                [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeContent:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:self.managedObjectContext.persistentStoreCoordinator];
                }

                And here are the event handler methods:

                #pragma mark - iCloud Methods
                - (void)storesWillChange {
                NSLog(@"\n\nStores WILL change notification received\n\n");
                // disbale UI
                [[UIApplication sharedApplication]beginIgnoringInteractionEvents];
                // save and reset our context
                if (self.managedObjectContext.hasChanges) {
                [self.managedObjectContext save:nil];
                } else {
                [self.managedObjectContext reset];
                }
                }
                - (void)storesDidChange:(NSNotification *)notification {
                NSLog(@"\n\nStores DID change notification received\n\n");
                // enable UI
                [[UIApplication sharedApplication]endIgnoringInteractionEvents];
                // update UI
                [self.tableView reloadData];
                }
                - (void)mergeContent:(NSNotification *)notification {
                NSLog(@"Merge Content here");
                [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
                }

                Demo Project

                Here’s the demo project that I’m building. Don’t forget to change the Bundle ID and your Team ID to make it work on your devices:

                • https://github.com/versluis/CoreData-with-iCloud-Screencast
                • Enjoy creating some rad iCloud apps

                  Further Reading
                  • http://pinkstone.co.uk/how-to-test-why-your-icloud-core-data-store-was-changed/
                  • https://developer.apple.com/LIBRARY/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html#//apple_ref/doc/uid/TP40013491-CH1-SW1
                  • http://stackoverflow.com/questions/21977191/icloud-coredata-notification-when-changed-to-icloud-store-first-launch-with
                  • Watch the whole series
                    • Part 1 is about Setup and Prep Work
                    • Part 2 is about using Key/Value Storage
                    • Part 3 is about using Document Storage
                    • Part 4 is about using Core Data with iCloud
                    • and Part 5 is about the initial import into the Core Data store
                    • Enjoy!

                      Watch the full course in one convenient playlist:
                      Catch this episode on my iOS Dev Diary Podcast:

                      33 min
                    • iCloud in your iOS Apps – Part 3: Document Storage

                      In this part I’ll show you how to use your app’s ubiquitous folder to store arbitrary files in a user’s iCloud store. We’re not going to cover the UIDocument class here because it adds a layer of complexity to an already difficult subject, and for simple files it’s just not necessary. We’ll also cover how to download new files if iCloud changes have been detected.

                      There are two code snippets I’m referencing here: one is the method to retrieve your iCloud Documents folder (don’t forget to make it public like I did). This one goes into the AppDelegate.m:

                      - (NSURL *)applicationCloudFolder:(NSString *)fileName {
                      // Team ID and Container ID
                      NSString *teamID = @"ABCDEF1234"; // add your own team ID here
                      NSString *bundleID = [NSBundle mainBundle].bundleIdentifier;
                      NSString *containerID = [NSString stringWithFormat:@"%@.%@", teamID, bundleID];
                      // URL to cloud folder
                      NSURL *cloudRootURL = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:containerID];
                      NSURL *cloudDocuments = [cloudRootURL URLByAppendingPathComponent:@"Documents"];
                      // append our file name
                      cloudDocuments = [cloudDocuments URLByAppendingPathComponent:fileName];
                      return cloudDocuments;
                      }

                      I’m also talking about the NSMetadataQuery which will detect changes in your iCloud Documents folder. This is a custom initialiser so you’ll need to create a property for it. Here’s the initialiser – in the video I’m using it in my ViewController class:

                      - (NSMetadataQuery *)query {
                      if (!_query) {
                      _query = [[NSMetadataQuery alloc]init];
                      NSArray *scopes = @[NSMetadataQueryUbiquitousDocumentsScope];
                      _query.searchScopes = scopes;
                      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K like %@", NSMetadataItemFSNameKey, @"*"];
                      _query.predicate = predicate;
                      if (![_query startQuery]) {
                      NSLog(@"Query didn't start... for whatever reason");
                      }
                      }
                      return _query;
                      }

                      To kick this into action you’ll also need to add an observer under viewDidLoad:

                      - (void)viewDidLoad
                      {
                      [super viewDidLoad];
                      // observe changes in iCloud folder
                      [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(populateUI) name:NSMetadataQueryDidUpdateNotification object:self.query];
                      }

                      Watch the whole series
                      • Part 1 is about Setup and Prep Work
                      • Part 2 is about using Key/Value Storage
                      • Part 3 is about using Document Storage
                      • Part 4 is about using Core Data with iCloud
                      • and Part 5 is about the initial import into the Core Data store
                      • Enjoy!

                        Watch the full course in one convenient playlist:
                        Catch this episode on my iOS Dev Diary Podcast:

                        32 min
                      • iCloud in your iOS Apps – Part 2: Key/Value Storage

                        In this part I’ll show you how to store and retrieve data using the NSUbiquitousKeyValueStore singleton, and how to receive the relevant notification so that your app can react if data has changed in iCloud.

                        Watch the whole series
                        • Part 1 is about Setup and Prep Work
                        • Part 2 is about using Key/Value Storage
                        • Part 3 is about using Document Storage
                        • Part 4 is about using Core Data with iCloud
                        • and Part 5 is about the initial import into the Core Data store
                        • Enjoy!

                          Watch the full course in one convenient playlist:
                          Catch this episode on my iOS Dev Diary Podcast:

                          13 min
                        • iCloud in your iOS Apps – Part 1: Setup

                          In this 5-part series I’ll show you how to use iCloud in your iOS Apps. We’ll discuss the whole picture, starting with how to setup Xcode and your app, including App ID and Provisioning Profiles and I’ll demonstrate how to use all three flavours of iCloud:

                          • Key Value Storage
                          • Document Storage
                          • and iCloud with Core Data
                          • Setup and Prep Work

                            In this part I’ll explain how to create an App ID, a Developer Provisioning Profile and how to import it into Xcode. We’ll also discuss what else needs to be setup in Xcode to make your app work with iCloud, no matter which flavour you want to use.

                            Watch the whole series
                            • Part 1 is about Setup and Prep Work
                            • Part 2 is about using Key/Value Storage
                            • Part 3 is about using Document Storage
                            • Part 4 is about using Core Data with iCloud
                            • and Part 5 is about the initial import into the Core Data store
                            • Enjoy!

                              Watch the full course in one convenient playlist:
                              Catch this episode on my iOS Dev Diary Podcast:

                              16 min
                            • How to dismiss the keyboard from a UITextField in iOS

                              In this episode I’ll show you how to dismiss the iOS Keyboard, which is commonly brought up by a UITextField – but doesn’t want to leave easy once summoned.

                              It’s easy to overlook a step in this procedure, so I thought a screencast is in order. We’re discussing two dismissal options here:

                              • when the DONE button is pressed
                              • and when users tap outside the textfield
                              • The latter option isn’t built into iOS, but users have come to rely on this behaviour. I’m using Xcode 5.1.1 and iOS 7.1 in this demo.

                                Happy hacking!

                                Steps in a nutshell

                                The trick is to implement a delegate method from the UITextField Protocol named textFieldShouldReturn. In it we need to tell the text field to resign its first responder status, giving up its “focus” so to speak.

                                Here’s the method:

                                - (BOOL)textFieldShouldReturn:(UITextField *)textField {
                                [self.textField resignFirstResponder];
                                NSLog(@"You said: %@", self.textField.text);
                                return YES;
                                }

                                We can use this method to utilise the actual text value of the input.

                                For this to work, the text field needs to know that your class is the delegate. Either hook it up to the orange square in Interface Builder and select delegate, or declare it in code:

                                - (UITextField *)textField {
                                _textField.delegate = self;
                                return _textField;
                                }

                                To make the keyboard go away when someone taps outside of it, drag out a huge button over the area that is not covered by the keyboard. Hook it up to a method and simply call the textFieldShouldReturn method to it. Even as of iOS 11, that’s the only way to make it work.

                                Watch the full course in one convenient playlist:
                                Catch this episode on my iOS Dev Diary Podcast:

                                16 min
                              • How to populate an NSTableView in code

                                I’ve previously shown you how to populate an NSTableView using Bindings and an array controller. Today I’ll show you how to do it in code.

                                It’s relatively simple and very similar to powering a UITableView. The main difference is that in Cocoa we don’t have a controller object that comes bundled with our view, so we’ll have to create one manually (or use an existing class). Here are the steps:

                                • add an NSTableView to your XIB file
                                • create a controller class based on NSObject (I’ll call mine TableController)
                                • drag an NSObject object into the XIB (that blue box)
                                • associate it with your custom controller object (i.e. TableController)
                                • set the data source and implement its methods
                                • In this example I’m using the numbers 1-10 in two arrays: as numbers, and as written out values – so that two columns of the table view can be populated with different items.

                                  #pragma mark - Custom Initialisers
                                  - (NSArray *)numbers {
                                  if (!_numbers) {
                                  _numbers = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10"];
                                  }
                                  return _numbers;
                                  }
                                  - (NSArray *)numberCodes {
                                  if (!_numberCodes) {
                                  _numberCodes = @[@"One", @"Two", @"Three", @"Four", @"Five", @"Six", @"Seven", @"Eight", @"Nine", @"Ten"];
                                  }
                                  return _numberCodes;
                                  }

                                  Next we’ll implement the following two methods: the first for returning the number of rows, and the second for returning the relevant data in each row:

                                  #pragma mark - Table View Data Source
                                  - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
                                  // how many rows do we have here?
                                  return self.numbers.count;
                                  }
                                  - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
                                  // populate each row of our table view with data
                                  // display a different value depending on each column (as identified in XIB)
                                  if ([tableColumn.identifier isEqualToString:@"numbers"]) {
                                  // first colum (numbers)
                                  return [self.numbers objectAtIndex:row];
                                  } else {
                                  // second column (numberCodes)
                                  return [self.numberCodes objectAtIndex:row];
                                  }
                                  }

                                  Notice that in the second method we’re not referencing the columns with a number (like we do with rows). That’s because the user could reorder or remove columns. Instead we’re using the column identifier which you can set in IB.

                                  Reacting to selections

                                  If you want to react to user selections in your code you need to implement the NSTableViewDelegate Protocol and also connect your table view’s delegate to the above class. Then simply implement this method and you’re notified when a user clicks a row:

                                  #pragma mark - Table View Delegate
                                  - (void)tableViewSelectionDidChange:(NSNotification *)notification {
                                  NSTableView *tableView = notification.object;
                                  NSLog(@"User has selected row %ld", (long)tableView.selectedRow);
                                  }

                                  Unlike in iOS, we’re not directly passed the table view object – but we can grab it from the notification. Note that the log message will be off by one because the rows start at 0 rather than 1.

                                  Demo Project

                                  Here’s a demo project with the above steps implemented:

                                  • https://github.com/versluis/Mac-TableViewCode
                                  • https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/protocols/nstabledatasource_protocol/reference/reference.html
                                  • Watch the full course in one convenient playlist:
                                    Catch this episode on my iOS Dev Diary Podcast:

                                    16 min

                                  About The iOS Dev Diary

                                  From the publisher's feed

                                  Fantastic Adventures in Objective-C