Tag Archives: Screencast

How to present a view controller on top of a UISplitView Controller

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!

This content is for members only.



Screencast: Building a searchable UITableView in iOS 9

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. Part 1 is free, and the remainder of the course is available to members of this website. You can also buy this course from Vimeo On Demand.

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 😉

This content is for members only.

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 🙂





How to build a UICollectionView in iOS 8

In this video 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 class and start fresh with a UICollectionViewController. Next I’ll add a custom class for the UICollectionViewController and UICollectionViewCell and then we’ll hook it up in the storyboard.

By the end we’ll have a simple Collection View App which allows multiple selections. I’m going to use this project to build on with other features in the future.

Custom CollectionViewController Class

The template provides a few good starting points, but they need to be changed to work. First there’s the cell’s reuse identifier, conveniently added as a static at the top of the implementation file. It’s there so we only need to change this once in the file. Replace it with your own, and remember to make the same change in the storyboard:

static NSString * const reuseIdentifier = @"Cell";

Screen Shot 2015-02-03 at 11.11.03

Next up is the viewDidLoad method. To make dequeuing cells easier, Apple have provided a registerClass method. If you don’t add your custom cell here, nothing will appear when you run the app. I found that simply commenting out the line works just as well.

The reason they provide this is so that the dequeueCellWithIdendifier method knows which custom cell class to instantiate (prior to iOS 6 it returned nil, but that check is no longer necessary).

I’m also adding multiple selections here, something that cannot be done in the storyboard.

- (void)viewDidLoad {

    [super viewDidLoad];
    
    // EVIL: Register your own cell class (or comment this out)
    [self.collectionView registerClass:[YourCustomCell class] forCellWithReuseIdentifier:reuseIdentifier];
    
    // allow multiple selections
    self.collectionView.allowsMultipleSelection = YES;
    self.collectionView.allowsSelection = YES;
    
}

UICollectionViewDataSource

Much like with UITableViews, we need to provide the number of sections, as well as the number of items in each section:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    return 1;
}


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return self.cellData.count;
}

If you don’t provide the sections method, it is assumed that you have one section. Usually we’d have some data and would return a count of how many items we have rather than fixed values here.

We also need to provide what’s in each cell. Here we can add data to labels, populate UIImageViews and many other things our collection view cells may need:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    cell.textLabel.text = [self.cellData objectAtIndex:indexPath.row];

    return cell;
}

UICollectionViewCell

With UITableViews there were four styles of table cells we could choose from out of the box. A collection view cell on the other hand is completely blank, and we’re expected to provide everything inside it. This means we need a custom UICollectionViewCell class for our project.

Anything we drag into the prototype cell in the storyboard can be hooked up to that custom class and the configured in the above cellForItemAtIndexPath method. Make sure any outlets are defined in the cell’s header file.

Cell Selections

Collection view cells have several views layered on top of each other. At the bottom is the backgroundView and the selectedBackgroundView. These are not configured by default, but if we add our own views here, the cell knows how display selections.

Above the background/selectedBackgroundView is the contentView, and on top of the contentView is where we can add out own outlets (like labels and images). If we leave the contentView’s background colour transparent, the views underneath will be visible, and hence selections are visible too.

Here’s how to configure our custom cell with two colours for selection and deselection. I’m doing this in awakeFromNib, which is called as soon as our cell is instantiated:

- (void)awakeFromNib {
    
    // standard background (deselected)
    UIView *bgView = [[UIView alloc]initWithFrame:self.bounds];
    self.backgroundView = bgView;
    self.backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue"]];
    
    // selected background
    UIView *selectedView = [[UIView alloc]initWithFrame:self.bounds];
    self.selectedBackgroundView = selectedView;
    self.selectedBackgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"pink"]];
    
}

Demo Project

The code I’m writing here is available as a demo project on GitHub:





How to create an Unwind Segue in iOS 8

The Unwind Segue was introduced in iOS 6 to make retrieving data from a dismissed view controller easier. A regular Segue allows us to send data from one view controller to another, but it’s not easy to bring data back if the user has changed or added details in that view controller. That’s where an Unwind Segue comes in.

Part 1: Code

Here’s how to create one. I’m assuming we have two view controllers at our disposal, ViewController1 has initiated a standard segue, maybe passing some data. The user then changes the data, and upon saving the data, ViewController2 is dismissed and we’re going back to ViewController1.

So in ViewController1 we’ll add a method we can use as an Unwind Segue, which we later hook up in the storyboard to the Exit object. Here’s that method:

- (IBAction)backToTheStart:(UIStoryboardSegue *)segue {
    
    // grab a reference
    ViewController2 *viewController2 = segue.sourceViewController;
    
    // access public properties from ViewController2 here
}

It doesn’t matter what the method is called, just as long as it resides in ViewController1, in which you’ve imported the ViewController2.h file. What DOES matter however that our method is an IBAction and takes a UIStoryboardSegue as a parameter – otherwise Interface builder won’t recognise it, and you won’t be able to drag to the Exit object later.

Meanwhile, in ViewController2, we can make use of the following method which is often provided as a stub in new view controller classes:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
    // do any preparation here when the segue is called
}

prepareForSegue is called just before the unwind segue (or any segue for that matter) is about to begin. You may want to read out a text field or any other values and add it to the object or variable that ViewController1 needs access to.

Part 2: Hooking up the Storyboard

With our code in place, control-drag from the button you’d like to use for initiating the segue. You can hook up multiple buttons to the same unwind segue.

Control-drag each button to the Exit object (in ViewController2):

Screen Shot 2015-01-29 at 12.00.49

As soon as the button is pressed, the unwind code in ViewController1 is executed and ViewController2 is dismissed.

Demo Project

I’ve put together a quick demo project on GitHub which is the code I’m creating the screencast above:

Further Reading





Creating Multiple In-App Purchases in iOS

In this screencast I’ll show you how to create multiple in-app purchases in you iOS app. The first part is a quick overview, and the second part shows how I’m tinkering with the code (members only).

This is based on an earlier tutorial in which I’m explaining how to create a single in-app purchase – if you’d like to follow along, you can find it here:

In a nutshell we’ll duplicate the earlier Shop class, add our new product identifier and amend the StoreKit observer method, as well as the alertView so that it can unlock the correct product.

The source code for this project is available on GitHub: the master branch is the earlier tutorial with a single product, and the Multi-IAP branch is what’s shown in this video.

This content is for members only.



How to reset your iCloud Ubiquitous Container

In this screencast I’ll show you how to reset your iCloud Ubiquity Container from an iOS device. This will clear up anything you’ve saved in iCloud Documents and iCloud Core Data and also simulates “first installation”.

Sometimes when you test the same app over and over the container can get corrupted, error messages start flooding in and ultimately your app doesn’t behave as expected – making you doubt your sanity, alienating your friends and family and giving you more grey hair then you need.

If the above still doesn’t work, turn your devices off and on again, restart Xcode and reboot your Mac – a useful tip often forgotten with pesky bugs that don’t make sense (thanks to Eric for reminding me of this).

In a nutshell:

  • remove your app from all devices – this is important because running apps, or existing apps launched will assume there’s data in iCloud and they will try to communicate with your (defunct) container
  • remote all data from the container as described in the video (on iOS, head over to Settings – iCloud – Manage Storage – find your app and select it, hit edit and delete all data)
  • now re-deploy the app to each device via Xcode

For Core Data: the first app that’s launched checks to see if data exists in iCloud, and if not will create the iCloud store. Subsequent apps will see this has been done and read the changes from those mysterious log files.

Removing the container in code

You can also call a method on the NSPersistentStoreCoordinator class to remove the entire ubiquity container. Here’s how to do that:

- (void)deleteCloudContainer {
    
    // remove this store's iCloud Content
    NSPersistentStore *currentStore = self.managedObjectContext.persistentStoreCoordinator.persistentStores.lastObject;
    NSError *error = nil;
    [self.managedObjectContext reset];
    [self.managedObjectContext.persistentStoreCoordinator removePersistentStore:currentStore error:nil];
    
    if (![NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:currentStore.URL options:currentStore.options error:&error]) {
        NSLog(@"Could not remove iCloud Container. Reason: %@", error.localizedFailureReason);
    }
}

This does pretty much the same thing as the manual method, although it may take a moment. Works in iOS 7, but I’ve not had much luck in iOS 8 Beta 5 (in fact, I’ve not had much luck with anything in iOS 8 Beta 5).