The iOS Dev Diary

Jay Versluis

Fantastic adventures in Objective-C

  • 19 minutes 59 seconds
    Building a Day Counter on iOS – Part 3

    In this series I’ll show you how to create a simple Day Counter on iOS, using Objective-C and Xcode 9. The idea is to set a date in a settings screen, and then see how many days have elapsed on the main screen right after launching the app.

    This is a 3-Part Mini-Series:

    • Part 1 is all about building the interface in Interface Builder
    • Part 2 is about coding the NSDate subtraction methods, using NSCalendar and loading/saving data using NSUserDefaults
    • Part 3 will introduce Key/Value Observing to update the first view controller as soon as the date is changed in the settings and deals with how to normalise an NSDate object.

    You can find the full code on GitHub:

    • https://github.com/versluis/Day-Counter/

    Happy Hacking!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    11 April 2018, 4:34 am
  • 28 minutes 54 seconds
    Building a Day Counter on iOS – Part 2

    In this series I’ll show you how to create a simple Day Counter on iOS, using Objective-C and Xcode 9. The idea is to set a date in a settings screen, and then see how many days have elapsed on the main screen right after launching the app.

    This is a 3-Part Mini-Series:

    • Part 1 is all about building the interface in Interface Builder
    • Part 2 is about coding the NSDate subtraction methods, using NSCalendar and loading/saving data using NSUserDefaults
    • Part 3 will introduce Key/Value Observing to update the first view controller as soon as the date is changed in the settings and deals with how to normalise an NSDate object.

    You can find the full code on GitHub:

    • https://github.com/versluis/Day-Counter/

    Happy Hacking!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    4 April 2018, 4:23 am
  • 19 minutes 18 seconds
    Building a Day Counter on iOS – Part 1

    In this series I’ll show you how to create a simple Day Counter on iOS, using Objective-C and Xcode 9. The idea is to set a date in a settings screen, and then see how many days have elapsed on the main screen right after launching the app.

    This is a 3-Part Mini-Series:

    • Part 1 is all about building the interface in Interface Builder
    • Part 2 is about coding the NSDate subtraction methods, using NSCalendar and loading/saving data using NSUserDefaults
    • Part 3 will introduce Key/Value Observing to update the first view controller as soon as the date is changed in the settings and deals with how to normalise an NSDate object.

    You can find the full code on GitHub:

    • https://github.com/versluis/Day-Counter/

    Happy Hacking!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    29 March 2018, 12:26 pm
  • 12 minutes 44 seconds
    How to present a view controller on top of a UISplitView Controller – Part 2

    The second part of this mini-series about presenting another UIViewController on top of a UISplitViewController in iOS 9 and Xcode 7.

    Check out the first part here, complete with code snippets and a link to the full project.

    Enjoy!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    6 December 2015, 5:56 am
  • 17 minutes 17 seconds
    How to present a view controller on top of a UISplitView Controller – Part 1

    SplitViewDemo

    Since its introduction in iOS 5, our good friend the UISplitView Controller has always had a really annoying habit: it has to be the root view controller in our apps. This means that it cannot be presented from any other view controller, nor can the split view controller present other view controllers.

    This sucks because 99% of all apps probably need to present a user choice overlay at some point during the lifetime of an app. While some apps may get away with showing a Popover on iPad, many apps would be better off if we could present something like a proper form sheet as pictured in the image above. However, by Apple’s definition, that’s just not possible with the split view controller.

    Or is it…?

    In this screencast I’ll show you how to make it appear as if we could present another view controller over a UISplitView Controller. We’ll employ a bit of magic to create a great user experience, and it’s not really difficult either. The whole thing works on both iPhone and iPad with no extra work, and it works with apps in Slideover Mode too.

    At the bottom of the article I’ll show you the code snippets to make this magic happen, together with a fully working demo project.

    Enjoy!

     

    Code Snippets

    The app is based on the Xcode Master/Detail template. Aside from hooking up two buttons to present and dismiss the overlay, all methods are conveniently called in AppDelegate. We need three methods in total.

    The first one will create a screenshot of whatever is currently on screen and return it as a UIImage:

    - (UIImage *)grabScreenshot { // create graphics context with screen size CGRect screenRect = [[UIScreen mainScreen] bounds]; UIGraphicsBeginImageContext(screenRect.size); CGContextRef ctx = UIGraphicsGetCurrentContext(); [[UIColor blackColor] set]; CGContextFillRect(ctx, screenRect); // grab reference to our window UIWindow *window = [UIApplication sharedApplication].keyWindow; // transfer content into our context [window.layer renderInContext:ctx]; UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screengrab; }

    I’m explaining how this method works and what it does  in this article.

    The next two methods need to be public, so let’s make sure their signature appears in our AppDelegate.h file, anywhere before the @end:

    - (void)showOverlay; - (void)dismissOverlay;

    Back in our AppDelegate.m file, here’s the first method:

    - (void)showOverlay { // grab a screenshot UIImage *screenshot = [self grabScreenshot]; // create a new view controller with it UIViewController *underlay = [[UIViewController alloc]init]; UIImageView *background = [[UIImageView alloc]initWithImage:screenshot]; underlay.view = background; // grab the overlay controller UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UINavigationController *overlay = (UINavigationController *)[storyboard instantiateViewControllerWithIdentifier:@"Overlay"]; overlay.modalPresentationStyle = UIModalPresentationFormSheet; // swap the split view self.splitView = (UISplitViewController *)self.window.rootViewController; self.window.rootViewController = underlay; // present the overlay [underlay presentViewController:overlay animated:YES completion:nil]; }

    Here we grab a screenshot using our previous method and create a brand new view controller with it, using the screenshot as a background. Because this is a standard UIViewController, we can present another view controller over it.

    While the screenshot is one ingredient to our magic, switching root view controllers is the other: we switch out the split view for our standard view controller (the “fake split view”) using self.window.rootViewController. This is only possible from the AppDelegate because it has access to the main window of our app. Switching is instantaneous and – as long as the content is the same – invisible to the human eye. Before we do this, we’ll grab a reference to the split view so we can bring it back in our next method.

    Our third method will dismiss the overlay again:

    - (void)dismissOverlay { // dismiss the overlay [self.window.rootViewController dismissViewControllerAnimated:YES completion:^{ // bring back the split view self.window.rootViewController = self.splitView; }]; }

    Here we dismiss the overlay and swap back to the split view controller we’ve grabbed a reference to earlier. We’ll do that in the completion block to make sure the animation has finished so nobody will notice what we’re doing.

    To finish off the magic presentation, we’ll call the showOverlay method from our master view controller with a 0.2 second delay. This will allow the button animation to finish before we take the screenshot, otherwise our app will take a capture with the “depressed” button. That’ll look unhandsome when we switch back to the real split view.

    Here’s how we do this “delayed firing”, via two methods in our MasterViewController.m file:

    # pragma mark - Split View Methods - (void)showOverlay { // wait a moment before taking the screenshot [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(showOverlayDelayed) userInfo:nil repeats:NO]; } - (void)showOverlayDelayed { AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; [appDelegate showOverlay]; }

    The first method is called when the user presses the actual button. All it does is wait for 0.2 seconds using an NSTimer. When the wait is over, it’ll call the second method, which in turn asks the AppDelegate to perform our showOverlay method.

    The end result is a seamless user experience, and it appears we’re presenting the overlay right over our split view. Is this cool or what?

    Demo Project

    Here’s the full project I’ve built in the screencast:

    • https://github.com/versluis/Screw-The-Split-View
    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    30 November 2015, 4:47 pm
  • 11 minutes 17 seconds
    Building a searchable UITableView in iOS 9 – Part 4

    In this final part of our project we’ll finish off the app by implementing a little Key Value Observation magic. This will let us update our second UITableViewController when new search results are to be displayed.

    Check out the first part here, as well as a link to my demo project.

    Enjoy!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    25 November 2015, 6:23 am
  • 7 minutes 55 seconds
    Building a searchable UITableView in iOS 9 – Part 3

    In this part of our series we’ll take a look at how we actually filter the data that is displayed in the searchable table view. We do that using an NSPredicate.

    Check out the first part here, as well as a link to my demo project.

    Enjoy!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    18 November 2015, 6:21 am
  • 11 minutes 29 seconds
    Building a searchable UITableView in iOS 9 – Part 2

    In the previous part we’ve setup our project and the relevant graphical bits to make the app display the table view. Now it’s time to implement the UISearchController object that will be at the heart of letting users sift through our search results. We’ll do that in this part.

    Check out the first part here, as well as a link to my demo project.

    Enjoy!

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    11 November 2015, 6:10 am
  • 23 minutes 25 seconds
    Building a searchable UITableView in iOS 9 – Part 1

    In this 4 part course I’ll show you how to build a searchable UITableView using iOS 9.1 and Xcode 7.1.

    • Part 1 will talk you through how to build a UITableView with dummy data
    • In Part 2 I’ll show you how to use a UISearchController to display a second table view
    • In Part 3 we’ll discuss how to filter results using an NSPredicate
    • And in Part 4 we’ll see how to communicate those search results to the second table view via KVO.

    The whole course is about 50 minutes long, and I’ll explain details step by step. All code is Objective-C, and the the full project I’m building is available on GitHub.

    Sounds interesting? Join me now and I’ll see you on the other side 😉

    Demo Project

    Here’s the code I’ve built during the screencast. As promised, I’ve also implemented the UISearchControllerDelegate methods – just in case you need them:

    Further Reading

    The Apple Class References aside, I’ve also put together written instructions on how to create this project in my next article. If you prefer written instructions, go check it out here – it covers the same steps as these videos 🙂

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    5 November 2015, 11:26 pm
  • 19 minutes 26 seconds
    How to load UIStoryboards depending on screen height in iOS

    A while ago I’ve written an article about how to load different storyboards depending on the screen size of an iOS device. Back in those days (2013) it was all a bit simpler than it is today, and I looked into it mainly because I loathed Auto Layout so much.

    I felt it was time for an update, so here it is!

    Things haven’t gotten any easier in iOS, because currently we have the following 5 screen sizes to deal with:

    • iPhone 6 Plus: 736×414 @3x
    • iPhone 6: 667×375 @3x
    • iPhone 5s: 568×320 @2x
    • iPhone 4s: 480×320 @2x
    • all iPads: 1024×768 @1x / @2x

    It’s very difficult to make a UI look nice on all devices with a single UIStoryboard, and in the above video I’m showing you an alternative: design a completely different storyboard for each screen size.

    The upkeep of such an app will be a little more complex, but it puts us in full control of the user experience, and not some compromise that sounds good in the Apple presentation (and sucks in reality).

    In principle, the following steps are involved:

    • design various storyboards
    • detect the current device’s screen height
    • load the appropriate storyboard
    • make it “key and visible”

    Detecting the screen size

    If your app is set to “auto-rotate” (i.e. both portrait and landscape modes, or portrait only), the screen height will detect the longer side of the screen. This is true even if the app is started in landscape mode. Determining screen height can be done like this:

    int screenHeight = [UIScreen mainScreen].bounds.size.height; NSLog(@"Screen Height is %i", screenHeight);

    Note that if you set your app to “landscape only” mode, the height parameter will return the shorter side of the screen – in which case, bounds.size.width to determine the longer portion of the screen. Thanks to Johan Grip for bringing this to my attention!

    iOS 7 compatibility

    Note that the screen size is orientation dependant since iOS 8 – previous versions did not take this into a account. If you must support iOS 7 and earlier it gets a lot more complicated (and I won’t cover this here – sorry).

    However, this Stack Overflow discussion may help you in that case: http://stackoverflow.com/questions/24150359/is-uiscreen-mainscreen-bounds-size-becoming-orientation-dependent-in-ios8

    Loading the correct UIStoryboard

    With this handy integer in place, we can build a switch statement to react according to the screen height. I’m using the following method that returns my desired storyboard in my AppDelegate implementation file.

    If you’re not worried about each single size, feel free to write a shorter if/then/else type method.

     

    - (UIStoryboard *)grabStoryboard { // determine screen size int screenHeight = [UIScreen mainScreen].bounds.size.height; UIStoryboard *storyboard; switch (screenHeight) { // iPhone 4s case 480: storyboard = [UIStoryboard storyboardWithName:@"Main-4s" bundle:nil]; break; // iPhone 5s case 568: storyboard = [UIStoryboard storyboardWithName:@"Main-5s" bundle:nil]; break; // iPhone 6 case 667: storyboard = [UIStoryboard storyboardWithName:@"Main-6" bundle:nil]; break; // iPhone 6 Plus case 736: storyboard = [UIStoryboard storyboardWithName:@"Main-6-Plus" bundle:nil]; break; default: // it's an iPad storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; break; } return storyboard; }

     

    Displaying the storyboard

    Inside our AppDelegate method didFinishLaunchingWithOptions, we’ll call the above method and grab the storyboard we need. To make it show up, we need to load it as the window’s root view controller and declare it “key and visible”. This is akin to the old-style way of making things appear on our iOS screens.

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // grab correct storyboard depending on screen height UIStoryboard *storyboard = [self grabStoryboard]; // display storyboard self.window.rootViewController = [storyboard instantiateInitialViewController]; [self.window makeKeyAndVisible]; return YES; }

    Note that using this approach will override whatever storyboard is declared in your target (under General – Deployment Info – Main Interface).

     

    Demo Project

    I’ve updated this project on GitHub, it shows exactly what I’m building in the screencast. Play and enjoy 🙂

    Watch the full course in one convenient playlist:
    YouTube-Badge.png?w=604&ssl=1Catch this episode on my iOS Dev Diary Podcast:
    Apple-Podcasts-Badge.png?w=604&ssl=1
    Stitcher-Badge.png?w=604&ssl=1
    19 May 2015, 7:28 pm
  • 26 minutes 55 seconds
    How to build a UICollectionView in iOS 8
    In this episode I’ll show you how to build a UICollectionView from scratch in Xcode 6. The class is available for both iPhone and iPad since iOS 6. If you know how to build a UITableView then building a UICollectionView will be familiar to you. I’ll start with a single view application, delete the ViewController … Continue reading How to build a UICollectionView in iOS 8
    2 February 2015, 5:48 pm
  • More Episodes? Get the App