Recent Updates Toggle Comment Threads | Keyboard Shortcuts

  • versluis 3:28 pm on May 19, 2015 Permalink | Reply
    Tags: UIScreen,   

    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 was 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 height

    The screen height is always detected as the longer side of the screen, at least according to my tests and experiences. 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);


    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];
                // iPhone 5s
                case 568:
                storyboard = [UIStoryboard storyboardWithName:@"Main-5s" bundle:nil];
                // iPhone 6
                case 667:
                storyboard = [UIStoryboard storyboardWithName:@"Main-6" bundle:nil];
                // iPhone 6 Plus
                case 736:
                storyboard = [UIStoryboard storyboardWithName:@"Main-6-Plus" bundle:nil];
                // it's an iPad
                storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        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 :-)

  • versluis 12:21 pm on April 11, 2015 Permalink | Reply
    Tags: ,   

    What's new in iOS 8.3 and Xcode 6.3 

    iOS 8.3 includes improved performance, bug fixes, and a redesigned Emoji keyboard. Changes include:

    Improved performance for:

    • App launch
    • App responsiveness
    • Messages
    • Wi-Fi
    • Control Center
    • Safari tabs
    • 3rd-party keyboards
    • Keyboard shortcuts
    • Simplified Chinese keyboard

    Wi-Fi and Bluetooth fixes

    • Fixes an issue where you could be continuously prompted for login credentials
    • Addresses an issue where some devices disconnect intermittently from Wi-Fi networks
    • Fixes an issue where hands-free phone calls could become disconnected
    • Fixes an issue where audio playback could stop working with some bluetooth speakers

    Orientation and rotation fixes

    • Addresses an issue that sometimes prevented rotating back to portrait after having rotated to landscape
    • Improves performance and stability issues that occurred when rotating the device between portrait and landscape
    • Fixes an issue where device orientation appeared upside down after pulling the iPhone 6 Plus from your pocket
    • Resolves an issue that sometimes prevented apps from rotating to correct orientation after switching apps in multitasking

    Messages fixes

    • Addresses issues that caused group messages to sometimes split
    • Fixes an issue that sometimes removed the ability to forward or delete individual messages
    • Resolves an issue that sometimes prevented a preview from appearing when taking a photo in Messages
    • Adds the ability to report junk messages directly from the Messages app
    • Adds the ability to filter out iMessages that are not sent by your contacts

    Family Sharing fixes

    • Fixes a bug where certain apps would not launch or update on family members’ devices
    • Fixes a bug that prevented family members from downloading certain free apps
    • Increased reliability for Ask to Buy notifications

    CarPlay fixes

    • Fixes an issue where Maps could come up as a black screen
    • Fixes an issue where the UI could be incorrectly rotated
    • Fixes an issue where the keyboard could appear on the CarPlay screen when it shouldn’t

    Enterprise fixes

    • Improves reliability of installing and updating enterprise apps
    • Corrects the time zone of Calendar events created in IBM Notes
    • Fixes a problem that could cause web clip icons to become generic after restarting
    • Improves reliability of saving the password for a web proxy
    • Exchange out-of-office message can now be edited separately for external replies
    • Improves recovery of Exchange accounts from temporary connection problems
    • Improves compatibility of VPN and web proxy solutions
    • Allows use of physical keyboards to log into Safari web sheets, such as for joining a public Wi-Fi network
    • Fixes an issue that caused Exchange meetings with long notes to be truncated

    Accessibility fixes

    • Fixes an issue where using the back button in Safari causes VoiceOver gestures to not respond
    • Fixes an issue where VoiceOver focus becomes unreliable in draft Mail messages
    • Fixes an issue where Braille Screen Input cannot be used to type text in forms on webpages
    • Fixes an issue where toggling Quick Nav on a Braille Display announces that Quick Nav is off
    • Fixes an issue keeping app icons from being moveable on home screen when VoiceOver is enabled
    • Fixes an issue in Speak Screen where speech will not start again after pausing

    Other improvements and bug fixes

    • Introduces a redesigned Emoji keyboard with over 300 new characters
    • iCloud Photo Library has been optimized to work with the new Photos app on OS X 10.10.3 and is now out of beta
    • Improves the pronunciation of street names during turn-by-turn navigation in Maps
    • Includes support for Baum VarioUltra 20 and VarioUltra 40 braille displays
    • Improves the display of Spotlight results when Reduce Transparency is turned on
    • Adds Italic and Underline format options for iPhone 6 Plus landscape keyboard
    • Adds the ability to remove shipping and billing addresses used with Apple Pay
    • Additional language and country support for Siri: English (India, New Zealand), Danish (Denmark), Dutch (Netherlands), Portuguese (Brazil), Russian (Russia), Swedish (Sweden), Thai (Thailand), Turkish (Turkey)
    • Additional dictation languages: Arabic (Saudi Arabia, United Arab Emirates) and Hebrew (Israel)
    • Improves stability for Phone, Mail, Bluetooth connectivity, Photos, Safari tabs, Settings, Weather and Genius Playlists in Music
    • Addresses an issue where Slide to Unlock could fail to work on certain devices
    • Addresses an issue that sometimes prevented swiping to answer a phone call on the Lock screen
    • Addresses an issue that prevented opening links in Safari PDFs
    • Fixes an issue where selecting Clear History and Website Data in Safari Settings did not clear all data
    • Fixes an issue that prevented autocorrecting “FYI”
    • Addresses an issue where contextual predictions did not appear in Quick Reply
    • Fixes an issue where Maps did not enter night mode from hybrid mode
    • Resolves an issue that prevented initiating FaceTime calls from a browser or 3rd-party app using FaceTime URLs
    • Fixes an issue that sometimes prevented photos from properly exporting to Digital Camera Image folders on Windows
    • Fixes an issue that sometimes prevented an iPad backup from completing with iTunes
    • Fixes an issue that could cause Podcast downloads to stall when switching from Wi-Fi to cellular networks
    • Fixes an issue where remaining time on timer would sometimes incorrectly display as 00:00 on Lock screen

    What’s new in Xcode 6.3

    Screen Shot 2015-04-11 at 12.25.30

    Apple have the following document available which explains the changes in Xcode better than the above screenshot:

    Further Reading

  • versluis 10:23 am on March 12, 2015 Permalink | Reply

    What’s new in iOS 8.2 

    Screen Shot 2015-03-12 at 10.44.02This release introduces support for Apple Watch, and also includes improvements to the Health app, increased stability and bug fixes.

    Apple Watch support

    • New Apple Watch app to pair and sync with iPhone, and to customize watch settings
    • New Activity app for viewing fitness data and achievements from Apple Watch; appears when Apple Watch is paired
    • Available on iPhone 5 and later

    Health app improvements

    • Adds the ability to select the unit of measurement for distance, body temperature, height, weight and blood glucose
    • Improves stability when dealing with large amounts of data
    • Includes the ability to add and visualize workout sessions from 3rd-party apps
    • Addresses an issue that may have prevented users from adding a photo in Medical ID
    • Fixes units for vitamins and minerals
    • Fixes an issue where Health data wouldn’t refresh after changing data source order
    • Fixes an issue where some graphs showed no data values
    • Adds a privacy setting that enables turning off tracking of steps, distance and flights climbed

    Stability enhancements

    • Increases stability of Mail
    • Improves stability of Flyover in Maps
    • Improves stability of Music
    • Improves VoiceOver reliability
    • Improves connectivity with Made for iPhone Hearing Aids

    Bug fixes

    • Fixes an issue in Maps that prevented navigating to some favorite locations
    • Addresses an issue where the last word in a quick reply message wasn’t autocorrected
    • Fixes an issue where duplicate iTunes purchased content could prevent iCloud restore from completing
    • Resolves an issue where some music or playlists didn’t sync from iTunes to the Music app
    • Fixes an issue where deleted audiobooks sometimes remained on device
    • Resolves an issue that could prevent call audio from routing to car speakers while using Siri Eyes Free
    • Fixes a Bluetooth calling issue where no audio is heard until the call is answered
    • Fixes a timezone issue where Calendar events appear in GMT
    • Addresses an issue that caused certain events in a custom recurring meeting to drop from an Exchange calendar
    • Fixes a certificate error that prevented configuring an Exchange account behind a third-party gateway
    • Fixes an issue that could cause an organizer’s Exchange meeting notes to be overwritten
    • Resolves an issue that prevented some Calendar events from automatically showing as ‘Busy’ after accepting an invite

    For information on the security content of this update, please visit this website:

  • versluis 11:57 am on February 3, 2015 Permalink | Reply

    How to implement context menus for cut/copy/paste in a UICollectionView 

    Screen Shot 2015-02-03 at 11.56.47

    By default a collection view cell is implementing a long press gesture recogniser. If activated the cell will bring up the familiar context menu for cut, copy and paste. It’s up to us to enable it, and it’s also up to us how to react to this menu. Here’s how we can do that.

    The following three methods are provided as commented stubs in the CollectionViewController template.

    Showing the Menu

    First we need to tell our class that the menu is to be shown:

    - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
    	return YES;

    Returning YES here will show the menu for every cell, but since we also get an indexPath, we could make decisions based on which cell has been tapped and make the menu show up conditionally.

    Next we need to decide which items we want to show:

    - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    	return YES;

    Returning YES here will show cut, copy and paste. We can make this conditional too, based both in the indexPath for each cell, but also based on the action parameter. Here’s a variation which will only show cut and paste, but not copy:

    - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
        // no copy option please
        if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) {
            return NO;
    	return YES;

    Menu Actions

    It’s up to us what happens when either of those menu items is selected by the user. We can either use the UIPasteboard to retrieve and store our values, or create a property and store out entire object in it. I only have an NSString value per cell and will use the UIPasteboard.

    This method is called when the user taps a menu item:

    - (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
        // Cut
        if ([NSStringFromSelector(action) isEqualToString:@"cut:"]) {
            // grab our value
            NSString *value = [self.cellData objectAtIndex:indexPath.row];
            // copy object to pasteboard
            [UIPasteboard generalPasteboard].string = value;
            // remove item
            [self.cellData removeObjectAtIndex:indexPath.row];
        // Copy
        if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) {
            // grab our value
            NSString *value = [self.cellData objectAtIndex:indexPath.row];
            // copy object to pasteboard
            [UIPasteboard generalPasteboard].string = value;
        // Paste
        if ([NSStringFromSelector(action) isEqualToString:@"paste:"]) {
            // grab our value
            NSString *value = [UIPasteboard generalPasteboard].string;
            // insert at current position
            [self.cellData insertObject:value atIndex:indexPath.row];
        // then reload the collection view
        [self.collectionView reloadData];

    It looks more complex than it really is: we first procure the value of our cell, and then add it to (or remove it from) the underlying data source. Typically it’s a mutable array or Core Data. Once the data is updated, we ask the collection view to reload its data which then makes the changes appear.

    That’s it!

compose new post
next post/next comment
previous post/previous comment
show/hide comments
go to top
go to login
show/hide help
shift + esc
Password Reset
Please enter your e-mail address. You will receive a new password via e-mail.