Recent Updates Toggle Comment Threads | Keyboard Shortcuts

  • Jay Versluis 5:32 pm on August 9, 2014 Permalink | Reply
    Tags: Pinterest, ,   

    How to open the Pinterest App from your own iOS App 

    Pinterest_Badge_RedYou can open Pinterest links from your iOS app directly in the Pinterest app if it’s installed. This includes direct links to a user, a user’s board, or a specific pin.

    In the following code snippets we’ll do just that, and if the Pinterest App is not installed on the device we’ll open the link in Safari instead. These methods can be hooked up to a UIButton.

    Note that for this to work, users need to be logged in to the Pinterest App – otherwise the app opens with a login prompt and not the link we want.

    Opening a Pinterest User Profile

    Much like on Twitter, users on Pinterest have handles. Mine is versluis2000, and my Pinterest URL is http://www.pinterest.com/versluis2000. Here’s how you open this user via the Pinterest app:

    - (IBAction)openPinterestUser:(id)sender {
        
        // open the Pinterest App if available
        if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"pinterest://user/juliav1"]]) {
            
            // opening the app didn't work - let's open Safari
            if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.pinterest.com/versluis2000/"]]) {
                
                // nothing works - perhaps we're not online
                NSLog(@"Dang!");
            }
        }
    }
    

    Trying to display your own Pinterest User Profile may crash the Pinterest App – at least that’s what happened in my tests.

    Opening a Pinterest Board

    Users on Pinterest can pin links to their boards which work like collections or categories. Those boards have slugs that appear after the user handle. I have a board called iOS Projects which has the following URL: http://www.pinterest.com/versluis2000/ios-projects/

    Here’s how we can open one directly in the Pinterest App:

    - (IBAction)openPinterestBoard:(id)sender {
        
        // open the Pinterest App if available
        if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"pinterest://board/versluis2000/ios-projects"]]) {
            
            // opening the app didn't work - let's open Safari
            if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.pinterest.com/versluis2000/ios-projects/"]]) {
                
                // nothing works - perhaps we're not online
                NSLog(@"Dang!");
            }
        }
    }
    

    Opening a Pinterest Pin

    When a user finds a link on the web and pins it, the link will receive a unique numeric ID. Such an ID is independent from the user who pins it. Here’s a pin to a sketch of a Polaroid camera I drew: http://www.pinterest.com/pin/76279787413881109/

    Let’s open this pin in the Pinterest App:

    - (IBAction)openPinterestPin:(id)sender {
        
        // open the Pinterest App if available
        if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"pinterest://pin/76279787413881109"]]) {
            
            // opening the app didn't work - let's open Safari
            if (![[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.pinterest.com/pin/76279787413881109/"]]) {
                
                // nothing works - perhaps we're not online
                NSLog(@"Dang!");
            }
        }
    }
    

    How about pinning something directly from my own app?

    If you’d like users to pin something directly from your app, take a look at the iOS Pin It SDK – brought to you by the friendly folks at Pinterest. The article also explains the deep linking structure we’re using in the above examples:

    Care for a Demo Project? https://github.com/versluis/Pinterest

     
  • Jay Versluis 3:57 pm on August 3, 2014 Permalink | Reply
    Tags: , ,   

    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.
     
  • Jay Versluis 10:52 pm on July 28, 2014 Permalink | Reply
    Tags:   

    How to fix “The identity used to sign the executable is no longer valid” error in Xcode 

    Screen Shot 2014-07-28 at 22.17.57It happens to all of us: your Apple Developer Membership is up, you renew it for $99 per year and you think you can get back to work. But no. The friendly folks over there made sure that nothing lasts forever – including your Provisioning Profiles.

    The above error is easy to fix and only involves 57 steps per app. The abridged version:

    • head over to the Apple Member Center
    • find the Provisioning Profiles section
    • click the ones saying “invalid” or “expired”
    • edit and regenerate them
    • back in Xcode, refresh your profiles

    The principle has been the same for a while, but every year the position of those items changes a bit. Here are some screenshots for the few seconds that remain in July 2014. It’ll probably be all outdated as soon as I hit publish. But until then, here goes:

    Head over to http://developer.apple.com and hit Member Center at the top right. Find something like Certificates, Identifiers and Profiles:

    Screen Shot 2014-07-28 at 22.31.08

    It’s a link that takes you to a section similar to this:

    Screen Shot 2014-07-28 at 22.32.13

    Select Provisioning Profiles (under iOS or Mac Apps, depending on your app) and you’ll see a long list of all profiles you’ve ever created. Pay attention to anything that’s not green in the left hand column, indicating expired or invalid profiles:

    Screen Shot 2014-07-28 at 22.21.02

    Find the profile in question and hit Edit. For Development Provisioning Profiles, you’ll find that your Development Certificate is no longer selected. Simply select it, add (or remove) any devices for this profile, then click Generate at the bottom. The next screen will offer you to download said profile – but since we’re using Xcode 5 or 6 we can ignore this step.

    Screen Shot 2014-07-28 at 22.21.40

    Distribution Profiles behave much the same: your Distribution Profile is deselected. Simply select it and hit generate. Again ignore the generous download offer and select Done instead.

    All those little red and yellow symbols should look green and calm like this:

    Screen Shot 2014-07-28 at 22.22.27

    I know what you’re thinking: “Hey, I’ve got 30+ profiles sitting there – isn’t there a way to renew all of them in one fair swoop?” – Of course there isn’t, don’t be ridiculous!

    Back in Xcode

    Now that the profiles are fixed, let’s tell Xcode about them. Head over to

    Xcode – Preferences – Accounts – select the account in question – select View Details.

    On the bottom left corner of that window you’ll see something like a refresh icon. Click that and Xcode will communicate with the Member Center and pull in those new profiles.

    When Xcode has finished, hit “done” to close that window and head over to your target, select Build Settings and find the Code Signing section (you can search for it if that list is a little long and confusing for your taste).

    Reselect your provisioning profile and – in theory – Xcode should now deploy your app correctly.

    Notice that I said “in theory” – because sometimes this doesn’t work. In which case, you can try the following options:

    • Build – Clean
    • restart Xcode
    • close your project, then restart Xcode
    • remove the app from your device, restart Xcode and re-deploy
    • find a different hobby because profiles take all the fun out of developing with Xcode

    Idea for a bumper sticker: Honk if you hate Provisioning Profiles!

     
  • Jay Versluis 6:41 pm on July 26, 2014 Permalink | Reply
    Tags:   

    How to compare two NSDates 

    Screen Shot 2014-01-07 at 12.55.39Comparing NSDate objects should be as easy as comparing two numbers. But because NSDate objects are complex, it’s not an easy task.

    Lucky for us the NSDate class has several ways of dealing with this conundrum.

    Imagine in the following examples that we have the objects “today” and “myDate”, the latter of which we would like to compare to today. We want to know, is myDate earlier or later than today?

    earlierDate and laterDate

    The easiest two to remember (for me) are earlierDate and laterDate. Here’s how they work:

        if ([myDate laterDate:today] == myDate) {
            NSLog(@"myDate is LATER than today");
        } else {
            NSLog(@"myDate is EARLIER than today");
        }
        
        // likewise:
        if ([myDate earlierDate:today] == myDate) {
            NSLog(@"myDate is EARLIER than today");
        } else {
            NSLog(@"myDate is LATER than today");
        }
    

    laterDate returns the NSDate object which is later, earlierDate returns the earlier one.

    compare

    For those brains that are wired like a frigging computer we also have the compare method, which compares the results to three much less intuitive enumerations:

        if ([myDate compare:today] == NSOrderedAscending) {
            NSLog(@"myDate is EARLIER than today");
        }
        
        if ([myDate compare:today] == NSOrderedDescending) {
            NSLog(@"myDate is LATER than today");
        }
        
        if ([myDate compare:today] == NSOrderedSame) {
            NSLog(@"myDate and today are THE SAME DATE");
        }
    

    The latter option can be good if you need to make sure the two dates are identical.

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

    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).

     
    • Chrystian 10:00 pm on August 7, 2014 Permalink | Reply

      Hi, I’m working on a core data app and iCloud. I’m trying to sync both devices and also to have the existing data relaunched after iCloud has been enabled.

      What advices can you give me. I’m having a lot of trouble with the sql file. Should it be in the bundle or should I copy it from inside?

      Thanks

    • Fred 8:57 am on August 11, 2014 Permalink | Reply

      Not working here with IOS 8 beta 5 – I can do like in the video, but in the end the container is still there. If i trash the containers on my mac at ~/Library/Mobile Documents, the second after they ‘re back.
      Oh well…

      • Jay 3:02 pm on August 11, 2014 Permalink | Reply

        Hi Fred, that may be a bug indeed – not a lot is working in the current Beta of iOS 8 and Xcode 6 – slightly shocking considering it’s Beta 5 already. At least Apple are happy, never mind us users ey…

        You can remove the iCloud Container in code too – I’ve added how to do it above. Works fine in iOS 7, but not quite yet in iOS 8 Beta 5.

  • 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.

     
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.