Category Archives: iOS Development

How to fix http load errors in Xcode

In 2016, Apple have implemented a new rule that won’t let us load data from unsecured websites anymore. That’s those beginning with http:// instead of https:// (the latter ones are secured with an SSL certificate, and hence traffic is encrypted).

When you load an unsecured source, you’ll get an error message like this:

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

If a secured source of the data is available, it’s probably the easiest method to change the feed. However, if that’s not an option, we can convince Xcode to let our apps download what’s known as data from “arbitrary” sources. Here’s how to do it.

First, in Xcode, navigate to your project’s target and find the Info tab. The target is the one that has your app icon showing, NOT the blue Xcode icon (top left, in the Project Navigator).

Now right-click on any of the many lines and select “Add Row”. This adds a value to your Info.plist file. Notice a list that comes up. Either select “App Transport Security” (if you can find it), or type NSAppTransportSecurity (it usually auto-completes). The entry will change into App Transport Security.

Let’s add the appropriate values to this new entry now. Hover over your new row now and select the little plus icon that comes up, then choose “Allow Arbitrary Loads” from the list. Alternatively, type in NSALlowsArbitraryLoads. Again this value will change to Allow Arbitrary Loads. Notice that this entry is a BOOL, and it needs to be set to YES on the right hand side. Go ahead and do that.

This will be enough to allow HTTP loads inside your app from any URL. You can restrict this to only certain URLs or hosts by adding another entry to the App Transport Security line, namely “Exception Domains”. Add each domain to its own line, and only data from those will be allowed to load via HTTP. If you want to use restricted domains, make sure to set the Allow Arbitrary Loads value to NO.





How to break a for loop in Objective C

Did you know that we can break out of a for loop before it finishes? It’s true – and it works with both regular for loops, as well as fast enumeration (for…in loops). And we can do it in either of two ways.

Let’s imagine we have an array with one thousand words. We’re only interested in finding a single one, and at that point we want to stop the loop.

Breaking with the break statement

The break statement will get us out of a for loop and continue programme execution after the finishing bracket of the loop. Here’s an example with a regular for loop:

    for (int i=0; i<1000; i++) {

        NSString *word = [array objectAtIndex:i];
        if ([word isEqualToString:@"one"]) {

            // break the loop
            break;
        }
    }
    // execution continues here
    NSLog(@"We've broken from the loop.");

The break statement also works with fast enumeration:

    for (NSString *word in array) {

        if ([word isEqualToString:@"up"] || [word isEqualToString:@"the"]) {

            // break the loop
            break;
        }
    }

    // execution continues here
    NSLog(@"We've broken from the loop.");

Breaking with “goto label”

Goto sounds like an old BASIC command – and we can still use it in Objective C. It doesn’t work on its own though and needs an arbitrary label to which we can direct the loop after we’ve broken from it.

Here’s how we might do this with a regular for loop:

    for (int i=0; i<1000; i++) {

        NSString *word = [array objectAtIndex:i];

        if ([word isEqualToString:@"the"]) {

            // break the loop with a label
            goto myLabel;
        }
    }

    myLabel:;
    NSLog(@"We've broken from the loop.");

Notice that when we declare the label where we’d like the programme to continue, we must do so with a colon (and a semi colon to finish the line).

The same principle also works with fast enumeration:

    for (NSString *word in array) {

        if ([word isEqualToString:@"up"] || [word isEqualToString:@"the"]) {

            // break the loop
            goto outer;
        } 
    }

    myLabel:;
    NSLog(@"We've broken the loop.");




How to use a specific voice for text-to-speech in iOS

There are two ways of creating voices with which we can make iOS talk: creating a voice using a locale (classic), or creating a voice using a specific voice identifier (futuristic).

Let me show you both options here.

Classic and Easy

In this snipped we’re creating a voice with a certain dialect, British English in this case:

NSString *phrase = @"I'm listening.";

AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc]init];

AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:phrase];

AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-GB"];

utterance.voice = voice;

[synthesizer speakUtterance:utterance];

While very straightforward, we don’t know if the voice is going to be male or female. All we can specify is the language and dialect.

Futuristic and Specific

The above works fine and probably was enough when the speech synthesiser framework was introduced in iOS 7, but since then there are a myriad of other voices we can use in our applications. To specify one of them, we need a voice identifier.

Here’s how to do it:

NSString *phrase = @"I'm listening.";

AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc]init];

AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:phrase];

AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithIdentifier:@"com.apple.ttsbundle.Karen-compact"];

utterance.voice = voice;

[synthesizer speakUtterance:utterance];

The setup is almost the same, but instead of the voiceWithLanguage method, we’re using the voiceWithIdentifier method here.

Finding Voices

To see a list of all available voices on the device, we can access the speechVoices method of the AVSpeechVoices class. This will return an array of AVSpeechVoices, all of which have a name, quality and identifier property. The latter is what we’re looking for so we can create a specific voice.

Here’s a method lists all available voices on the current device:

- (void)listVoices {

    NSArray *allVoices = [AVSpeechSynthesisVoice speechVoices];

    for (AVSpeechSynthesisVoice *voice in allVoices) {
        
        NSLog(@"Voice Name: %@, Identifier: %@, Quality: %ld", voice.name, voice.identifier, (long)voice.quality);

    }
}

Not all voices may be installed on all devices. For example, Alex is an optional high quality voice that the user needs to download first before he will show up in this array.

The quality parameter either returns 1 for standard/low-res, or 2 for enhanced/hi-res voices. Again it is up to the user to enable the hi-res quality of a voice under Settings.





How to test if an NSArray or NSSet contains an object

There’s a handy method in the NSArray class that lets us check if an array contains a particular object or not. The containsObject method returns a BOOL for us to evaluate.

Consider this:

// create an array
NSArray *array = @[@"Apples", @"Pears" , @"Bananas"];

// check if Pears are in the array
if ([array containsObject:@"Pears"]) {
    NSLog(@"We have Pears.");
}

Likewise, we can check if our array does not contain a particular object by testing the opposite:

// check if Grapes are not in the array
if (![array containsObject:@"Grapes"]) {
    NSLog(@"But we don't have Grapes.");
}

Both the NSMutableArray and NSSet classes has the same method, so we can check for the (un-)presence of our objects in mutable arrays and sets the same way.





What’s new in iOS 10.2

iOS 10.2 introduces new features including the TV app (US Only), a new and unified experience for accessing your TV shows and movies across multiple video apps.

Emoji have been beautifully redesigned to reveal even more detail and over 100 new emoji have been added including new faces, food, animals, sports, and professions.

This update also includes stability improvements and bug fixes. Continue reading





How to turn an ISO language code into the language identifier

Oftentimes we deal with cryptic language abbreviations, such as en-GB or de-DE. While it’s more or less clear to us humans what this means, it would be nice to have a way to display something more readable to our users.

We can do this with a method from the NSLocale object. Consider this snippet:

NSString *code = @"en-GB";
NSLocale *locale = [NSLocale currentLocale];
NSString *translation = [locale displayNameForKey:NSLocaleIdentifier value:code];

NSLog(@"%@ is %@", code, translation);

// output:
en-GB is English (United Kingdom)

Here we translate en-GB into “English (United Kingdom)”. First we take the current device’s locale, then we use the displayNameForKey method to turn the ISO language code into a human readable description.

The beauty is that no matter what language the device is set to, iOS will display the translation in the matching locale. For example, on a German device, en-GB would be translated into “English (Vereinigtes Königreich)”. Even though Germans would probably never refer to the UK as that. But I digress.

This also works with abbreviated language codes, such as “en” (instead of en-GB). In that case, the output is simply “English” without the country identifier.

We can also force iOS to display the translation in a locale of our choice. Rather than using the currently selected locale on the device, we can pick one and display the output accordingly:

NSString *code = @"en-GB";
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"fr-FR"];
NSString *translation = [locale displayNameForKey:NSLocaleIdentifier value:code];

NSLog(@"%@ is %@", code, translation);

// output:
en-GB is anglais (Royaume-Uni)