Recent Updates Toggle Comment Threads | Keyboard Shortcuts

  • Jay Versluis 1:33 pm on July 22, 2014 Permalink | Reply
    Tags: , restore,   

    Completing an iCloud Restore when it’s stuck on apps deployed from Xcode 

    Screen Shot 2014-07-22 at 13.30.25

    When you update a device with a new iOS Version (beta or not) and restore an iCloud Backup, said backup gets stuck while trying to bring back your own apps that you have deployed with Xcode. The iCloud backup is only saving your app’s data, but not the actual bundle. The idea is that iCloud can bring those back from the App Store.

    This means that apps you’ve deployed from Xcode, say as test apps or those still in development, are not on the App Store and hence cannot be brought back. When iCloud restores, it tries really hard – and as a result gets stuck in an endless loop.

    The implication is that you cannot deploy a new iOS version over the air when this happens – because the previous restore needs to finish first before applying the new one. However, getting rid of those non-existent apps is impossible – because the standard “tap wiggle and press x” method doesn’t work. Neither does any of the other methods. This leaves us developers stuck with darkened icons like these and a never ending restore loop:

    Screen Shot 2014-07-22 at 13.31.00

    How do we fix’er, Cap’m?

    You can deal with this in several ways:

    Option 1: deploy the new iOS Version via iTunes and do not restore an iCloud backup. This however leaves you with lost data and is probably only good as a last resort, of if you don’t care about existing data.

    Alternatively you can restore an iCloud backup, but you’ll be stuck in the restore loop again – albeit with a new version of iOS.

    Option 2: re-deploy your old apps from Xcode to the device so the restore can finish. As soon as the last app is installed, the new iOS Version can be applied over the air.

    If you no longer have access to the old apps fear not: as long as you can remember the Bundle ID, just create a new dummy app with said Bundle ID and deploy that – it’ll make the app on the device “deletable” again. iCloud doesn’t care and will finish the restore.

    Note that you must bring back every old app and get rid of any dark icon you have on your springboard for this to work.

    Screen Shot 2014-07-22 at 13.31.11

    What if I don’t remember the Bundle ID’s?

    That’ll be a problem… You’ll have to guess. Usually when you deploy something with a title like “Test App”, then spaces in your Bundle ID will be replaced with a dash (as in com.yourdomain.Test-App). Capitalisation is important here: com.yourdomain.Test-App is seen as a different app than com.yourdomain.test-app.

    If you’re not sure about the title of your “dark apps” (because usually it says “Waiting” during the restore attempt), try to hold one down, then press the x as if you’re deleting them. The deletion will silently fail, but the standard iOS Alert View will be displayed asking if you’re sure – and in doing so will display the title of this app.

     
  • Jay Versluis 9:41 am on July 21, 2014 Permalink | Reply  

    How to test if your app needs an upgrade 

    Screen Shot 2014-07-21 at 09.37.32

    Sometimes you want to implement a new feature in your latest release which relies on an existing feature to be amended in some way. For example, you’ve added iCloud functionality to your app and now you need to upgrade the store file.

    It’s important that such internal upgrade routines only run once when necessary and not every time your user launches the app. The simplest way to do this is to set a user default value after the migration, and test if it exists on every run of your app. If it does, the migration is not necessary. If it does not, we haven’t upgraded the app yet.

    Here’s a quick example of how you can implement this. I’m doing this in the AppDelegate’s didFinishLaunchingWithOptions method:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // check if an upgrade is necessary
        if (![[NSUserDefaults standardUserDefaults]boolForKey:@"didWeUpgrade"]) {
            
            // let's upgrade
            [self upgradeApp];
            
            // and remember for next time
            [[NSUserDefaults standardUserDefaults]setBool:YES forKey:@"didWeUpgrade"];
            [[NSUserDefaults standardUserDefaults]synchronize];
        }
        
        return YES;
    }
    
    #pragma mark - Upgrade Checks
    
    - (void)upgradeApp {
        
        // add your upgrade code here
        NSLog(@"Just upgraded your app. On the next run, this does not happen again.");
    }
    

    Be wise with the choice of your naming conventions for BOOLs and methods and make a note of which version of your app needed this upgrade. For example, add something like “upgraded Core Data with new string values as of version 1.3″.

    I’m saying this because you may need to upgrade again with another feature in the future, and you don’t want to confuse yourself, or run the old upgrade routine again in error. Just thought I’d mention it – you’ll thank me later ;-)

    Here’s a quick demo project on GitHub:

     
    • amitsbajaj 2:10 pm on July 21, 2014 Permalink | Reply

      Thanks Jay for creating this and this is really perfect! :) I’m so sorry for yet another question.. I know I’m so close now!..

      So in my scenario:

      App Store version with data (no iCloud)
      Update to iCloud version
      Data migrates to iCloud
      Other devices pick up data *
      Run the app again and it doesn’t use the new “migrated” store **

      Starting with **, when I run the app again, because the user defaults not is true (i.e. it exists), it doesn’t go to the upgrade method, which makes sense, but the logging in the console now doesn’t reflect iCloud usage at all and it looks like it’s reverting back to using the local storage. So my question is, when I migrate to use the iCloud store the first time the app is run, how do I set it so that the app always uses that store instead of reverting back to the local store when iCloud is available, and the account is the same?

      I’ll ask this separately without wanting to confuse too many things!

      Thanks again Jay!

      • Jay 3:48 pm on July 21, 2014 Permalink | Reply

        No problem at all! Without seeing your code, my hunch is that the puzzle lies in the custom initialiser for the persistent store coordinator. That’s where you setup the store file, and that’s where you’ll either use iCloud with Core Data or not. Therefore, you need to find a way to “fork” the initialiser with a similar if/then statement as in the example above.

        So if the app has been upgraded, and now runs again, the initialiser needs to setup the persistent store coordinator with iCloud. If not, it needs to be set as it always has been.

        The easiest way to do this is to setup the options dictionary differently. Something like this:

        - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
        {
            if (_persistentStoreCoordinator != nil) {
                return _persistentStoreCoordinator;
            }
            
            NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Upgrade.sqlite"];
            NSError *error = nil;
            
            // get a reference to your iCloud URL
            NSURL *cloudURL = [self grabCloudPath:@"iCloud"];
            
            // setup options depending on migration
            NSDictionary *options = nil;
            if ([[NSUserDefaults standardUserDefaults]boolForKey:@"didWeUpgrade"]) {
                options = @{NSPersistentStoreUbiquitousContentURLKey: cloudURL};
            }
            
            _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
            if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }    
            
            return _persistentStoreCoordinator;
        }
        

        Let me know if that works for you (and if it makes sense).

    • amitsbajaj 5:07 pm on July 21, 2014 Permalink | Reply

      Thanks once again Jay! An amazing help. I thought after I wrote it that it’s a bit hard without code and I was putting something together when your answer came through and that worked like a charm. The forked if-else statement worked perfectly in the persistentStoreCoordinator, like you have in the snippet you posted.

      So the if is evaluating if the userDefaults does exist and it contains the iCloud options and else evaluates without userDefaults and it contains the non-icloud options. It works like a charm because when the second device is connected in, it shows there’s no user defaults and it migrates the data successfully, but the next time it’s run, it works like a charm showing that userDefaults does exist and therefore to use the iCloud options.

      Honestly, you’ve managed to in one day, help me out with issues I’ve been having for quite some time!

      Thanks so much for this – I really appreciate it :)

      • Jay 5:31 pm on July 21, 2014 Permalink | Reply

        I’m so glad it helped you! I know what it’s like – these things can drive you crazy. And I honestly thing that Apple could have made it all a little less complicated… Good luck with the app!

  • Jay Versluis 12:33 pm on July 13, 2014 Permalink | Reply
    Tags:   

    How to fix a Region Mismatch on your Apple ID 

    Screen Shot 2014-07-13 at 12.09.00I have two Apple ID’s: one for the UK and one for the US. It’s not a problem for an iOS device two switch between store regions, even though it’s an annoying user experience. It should happen automatically.

    However, I had a problem several times now whereby my UK account shows my US billing address – and even asks me to verify my payment details. Trouble is, the UK account shows my US billing address – something I’ve never setup, and hence it’s impossible to verify my credit card due to the region mismatch.

    Most Apple Support staff are clueless when you bring this problem up, because “it’s impossible for our system to do that”. I know it’s a strange one, so here’s some proof from iTunes:

    AppStoreRegionMismatch

    Before I forget how to fix this again, let me tell you HOW this problem came to be:

    Unbeknownst to me I had added the email address of my US account as an alternative email address to my UK account. The App Store really doesn’t like this, and hence mixes up the addresses – particularly because my UK account no longer has a credit card on file.

    How to fix the Region Mismatch Nightmare

    A very nice gentleman from Apple named Melvin had the solution – he suggested the following:

    • login to https://appleid.apple.com using the account that needs fixing
    • select your language at the bottom right if needed
    • click “Addresses” and remove outdated ones
    • edit the single remaining Address and change it to the desired region and country
    • edit your Phone Number (doesn’t have to match the region – I added a US phone number to my UK account, just make sure you add the correct country code)
    • hit save and log out

    This will fix the problem. It’s probably best to remove alternate email addresses that are associated with other accounts, otherwise this problem will come back to haunt you (under Name, ID and Email Addresses).

    When you first log in here, you may be prompted to change your password to a more up-to-date one. Mine for example did not begin with a capital letter, and Apple no longer allow such passwords.

    Back on your iOS device

    If you now try to buy something from the App Store on your iOS device you may still be greeted with the verification dialogue, showing your (outdated) address and credit card information.

    Fix this by selecting “NONE” under credit card, tweak your phone number, and the verification will be successful.

    Another mystery solved!

     
  • Jay Versluis 11:39 am on June 25, 2014 Permalink | Reply
    Tags: , Nuggets,   

    Core Dara Nugget #1: How to speak Core Data 

    In this screencast I’ll talk you through the lingo of Core Data: those scary classes and expressions that you’ll frequently come across. In fact, this is the start of a new series:

    Core Data Nuggets are bite-sized chunks about the framework. Dip in and out or watch them all in a row and learn how this super complicated framework works and what it has to offer.

    Don’t get overwhelmed by Core Data: it wants to help – it’s just not designed with humans in mind.

    As always, enjoy!

     
  • Jay Versluis 8:48 pm on June 16, 2014 Permalink | Reply
    Tags:   

    How to bring back Code Completion for @ literals in Xcode 6 

    xcode-6-iconWhen you create literals with the @ symbol for Objective C classes in Xcode 6 Beta 1, it appears the code completion is no longer working as it once was. You know, that friendly list that used to appear as soon as you type @ in Xcode 4 and 5.

    I’ve been pulling my hair out over this. I’ve even filed a bug report with Apple, who kindly got back to me telling me I’m seeing things: it was working fine at their end. I was stumped: my three dev systems all exhibited the same behaviour: no code completion when you type the @ symbol.

    Turns out that this is “the new default behaviour” in Xcode 6 and by all accounts a “feature -

    because we now need to hit the ESCAPE key to bring up that list:

    Screen Shot 2014-06-16 at 20.40.44

    I’ve heard from other users that similar code completion is absent even from Swift projects. Perhaps we’ll all get used to that ESCAPE key, unless these are bugs that will be ironed out over the next few iterations.

    Of course code completion needs to be enabled for this to work, it’s worth to check this under Xcode – Preferences – Text Editing:

    Screen Shot 2014-06-16 at 20.35.47

     
  • Jay Versluis 4:50 pm on June 9, 2014 Permalink | Reply
    Tags: ,   

    Creating an In-App Purchase in iOS 7 and Xcode 5.1 

    In this 7-part screencast series I’ll show you how to create an In-App Purchase in iOS 7 with Xcode 5.1.

    The course will run you through everything from setting up your product in iTunes Connect, creating a custom shop class for easy re-use, making “first contact” with the App Store and how to deal with its responses. I’ll explain the overall concept in Part 1.

    Parts 1+2 are free to watch. The rest is for members only.

    Part 2 describes how to setup your your app for use with In-App purchases. We’ll setup a new App ID in Member Center, and create a product in iTunes Connect.

    This content is for members only.

    I’m following my earlier two articles almost to the letter, here they are for reference:

     
    • Math 11:30 pm on July 9, 2014 Permalink | Reply

      You are The man! Thank you very much.

      Keep up the good work!

      • Jay 11:47 pm on July 9, 2014 Permalink | Reply

        Thanks, Math! Greatly appreciate your feedback.

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Password Reset
Please enter your e-mail address. You will receive a new password via e-mail.