Easily Overlooked New Features in iOS 7
Check out this list of easily overlooked features in iOS 7 – there will probably be a few you’ve never heard of! By .
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Easily Overlooked New Features in iOS 7
30 mins
- The Bad News, the Good News, and the Really Good News
- The Bad News: App-Breaking Changes
- 1. -[UIDevice uniqueIdentifier] is no more
- 2. UIPasteboard as shared area is now sandboxed
- 3. MAC addresses can’t be used to identify a device
- 4. iOS now requests user consent for apps to use the microphone
- The Good News: Enhancements & Deprecations
- 5. Implementation of -[NSArray firstObject]
- 6. Introduction of instancetype
- 7. Tint images with UIImage.renderingMode
- 8. Usage of tintColor vs barTintColor
- 9. Texture colors are gone
- 10. UIButtonTypeRoundRect has been deprecated in favor of UIButtonTypeSystem
- The Really Good News: New Features
- 11. Check which wireless routes are available
- 12. Get information about the cellular radio signal
- 13. Sync passwords between user’s devices via iCloud
- 14. Display HTML with NSAttributedString
- 15. Use native Base64
- 16. Check screenshots with UIApplicationUserDidTakeScreenshotNotification
- 17. Implement multi-language speech synthesis
- 18. Use the new UIScreenEdgePanGestureRecognizer
- 19. Realize Message.app behavior with UIScrollViewKeyboardDismissMode
- 20. Detect blinks and smiles with CoreImage
- 21. Add links to UITextViews
- Where to Go From Here?
iOS 7 has been out for some time now. By now, you’re undoubtedly aware of its groundbreaking visual design; you’re dabbled in the new APIs such as SpriteKit, UIKit Dynamics and TextKit; and as a developer you’ve probably taken at least a few first steps with Xcode 5.
However, this is one of the biggest iOS releases ever, especially in terms of new and deprecated features. Unless you’re the type to stay up all night reading the iOS 7 release notes, it’s pretty likely that there are one or two new changes that you might have overlooked.
We’ve compiled a handy (but non-exhaustive!) list of some of the more urgent and interesting changes in iOS 7. Have a read through and see what new gems you weren’t aware of before!
The Bad News, the Good News, and the Really Good News
There’s some bad news, good news, and really good news about iOS 7.
- The bad news: There are a few app-breaking changes in iOS 7 which you need be on top of right away. If you haven’t already taken a close look at these changes in iOS 7, then you’d do well to read up on them, as they have the capability to break your existing apps when run on iOS 7!
- The good news: A few of the features and APIs that you’re familiar with in iOS 7 have been enhanced — but there are a few other features that have been deprecated. Taking the time to review these changes would be a great investment in the future of your current iOS apps.
- The really good news: The introduction of OS7 really shook up the mobile development world, but out of that tumultuous event came a bunch of really neat new features that have the potential to give your apps an edge, and may even serve as a catalyst for dreaming up really innovative apps for the future.
This article breaks down the easily overlooked features in iOS 7 into these three categories. Feel free to use this table of contents to quickly jump to the section you’re interested in – or keep reading to learn about all the changes!
The Bad News: App-Breaking Changes
-[UIDevice uniqueIdentifier]
is no moreUIPasteboard
as shared area is now sandboxed- MAC addresses can’t be used to identify a device
- iOS now requests user consent for apps to use the microphone
The Good News: Enhancements & Deprecations
- Implementation of
-[NSArray firstObject]
- Introduction of
instancetype
- Tint images with
UIImage.renderingMode
- Usage of tintColor vs barTintColor
- Texture colors are gone
UIButtonTypeRoundRect
is deprecated in favor ofUIButtonTypeSystem
The Really Good News: New Features
- Check which wireless routes are available
- Get information about the cellular radio signal
- Sync passwords between user’s devices via iCloud
- Display HTML with
NSAttributedString
- Use native Base64
- Check screenshots with
UIApplicationUserDidTakeScreenshotNotification
- Implement multi-language speech synthesis
- Use the new
UIScreenEdgePanGestureRecognizer
- Realize Message.app behavior with
UIScrollViewKeyboardDismissMode
- Detect blinks and smiles with Core Image
- Add links to
UITextViews
The Bad News: App-Breaking Changes
This section is dedicated to changes that you probably noticed during your transition to iOS 7, but you might not have known just how deep the changes go — and how they may affect your apps. The fact that these changes are all related to user privacy should tip you off to how important user privacy is to Apple (and hence to you)!
1. -[UIDevice uniqueIdentifier] is no more
Apple has always taken the privacy of users quite seriously. -[UIDevice uniqueIdentifier]
was originally deprecated on iOS 5, but iOS 7 drops it altogether. Xcode 5 won’t even let you compile an app that contains a reference to -[UIDevice uniqueIdentifier]
! Additionally, the behavior of pre-iOS 7 apps that use -[UIDevice uniqueIdentifier]
has changed on iOS 7: instead of returning the device’s UUID, this call returns a string starting with FFFFFFFF
, followed by the hex value of -[UIDevice identifierForVendor]
.
2. UIPasteboard as shared area is now sandboxed
UIPasteboard
is used to share data among apps. While that isn’t an issue in itself, a problem arose when developers started to use it to store generated identifiers and share the identifiers with all other interested apps. One library using this trick is OpenUDID.
In iOS 7, pasteboards created with +[UIPasteboard pasteboardWithName:create:]
and +[UIPasteboard pasteboardWithUniqueName]
are now only visible to apps in the same application group, which makes OpenUDID much less useful than it once was.

It’s still fine to use this kind of Mac though
3. MAC addresses can’t be used to identify a device
Using the iOS device’s Media Access Control (MAC) address was another common approach to generate unique identifiers on iOS devices. A MAC address is a unique number assigned to the network adapter at the physical network level. Apple has alternate names for this address, such as “Hardware Address” or “Wi-Fi Address” in some cases, but these terms all refer to the same thing.
A lot of projects and frameworks used this approach to generate unique device IDs, such as ODIN. However, Apple doesn’t want anyone to potentially identify a user by their MAC address, so all calls to retrieve the MAC address on iOS 7 return 02:00:00:00:00:00
. That’s it. No crying. Put those tears away.
Apple made it pretty clear that you should use -[UIDevice identifierForVendor]
or -[ASIdentifierManager advertisingIdentifier]
as unique identifiers in your frameworks and applications. Frankly, it’s not all that hard to implement these changes, as shown in the code snippet below:
NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];
NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];
Each of these approaches is best suited to a specific use case:
-
identifierForVendor
is a value that is unique to the vendor; that is, all apps released by the same company running on the same device will have the same identifier. However, this value will change if the user deletes a vendor’s apps from their device and later reinstalls those same apps. So this scheme isn’t persistent. -
advertisingIdentifier
returns the same value to all vendors running on the same device and should only be used to serve up advertisements. This value too may change in some scenarios, such as when the user erases the device.
You can read more about the various approaches to in this post written by Ole Begemann.
4. iOS now requests user consent for apps to use the microphone
In previous versions, iOS prompted the user for permission to retrieve the user’s location to access their contacts, calendars, reminders and photos, to receive push notifications and to use their social networks. In iOS 7, access to the microphone is now on that list. If the user doesn’t grant permission for an app to use the microphone, then apps using the microphone will only receive silence.
Here’s a bit of code you can use to detect if your app has been given permission to access the microphone:
// The first time you call this method, the system prompts the user to grant your app access
// to the microphone; any other time you call this method, the system will not prompt the user
// and instead passes the previous value for 'granted'
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
if (granted) {
// the user granted permission!
} else {
// maybe show a reminder to let the user know that the app has no permission?
}
}];
Also note that using any methods to access the microphone before the user has granted permission will cause iOS to display the following alert:

Apps on iOS 7 needs to get your permission to access the microphone!
The Good News: Enhancements & Deprecations
So that’s it for the significant stuff that can break your existing apps. However, there’s a few enhancements and deprecations of existing APIs that may affect your apps in other ways that you might not notice at first glance.
5. Implementation of -[NSArray firstObject]
-[NSArray firstObject] is probably one of the most requested APIs in Objective-C. A simple search on Open Radar shows several requests that have been filed with Apple. The good news is that it’s finally available. firstObject
actually goes back as far as iOS 4.0, but only as a private method. Previously, developers worked around this in the following fashion:
NSArray *arr = @[];
id item = [arr firstObject];
// previously you had to do the following:
id item = [arr count] > 0 ? arr[0] : nil;
Since the above pattern was fairly common, several people added this as a category to NSArray
and created their own firstObject
method. Do a quick search on GitHub and you’ll see just how many times this has been implemented in the past.
The problem with this approach is that method names in categories should be unique, otherwise the behavior of this method can be unexpected. Apple recommends that you always prefix method names when creating categories on Framework classes. Be sure to check if you have any custom code that implements firstObject
on NSArray
and either preface it as necessary, or remove it entirely.
6. Introduction of instancetype
instancetype
has the effect of making iOS 7 APIs diffs a lot harder to read. Apple changed most initializers and convenience constructors to return instancetype
instead of id
. But what is this new keyword, anyway?
instancetype
is used in method declarations to indicate the return type to the compiler; it indicates that the object returned will be an instance of the class on which the method is called. It’s better than returning id
as the compiler can do a bit of error-checking against return types at compile time, as opposed to only detecting these issues at run time. It also does away with the need to cast the type of the returned value when calling methods on subclasses.
The long and short of instancetype
? Basically, use it whenever possible.
You can read more about instancetype
in What’s New in Objective-C and Foundation in iOS 7 by Matt Galloway, as well as on NSHipster.
7. Tint images with UIImage.renderingMode
Tinting is a big part of the new look and feel of iOS 7, and you have control whether your image is tinted or not when rendered. UIImage
now has a read-only property named renderingMode
as well as a new method imageWithRenderingMode:
which uses the new enum UIImageRenderingMode
containing the following possible values:
UIImageRenderingModeAutomatic // Use the default rendering mode for the context where the image is used
UIImageRenderingModeAlwaysOriginal // Always draw the original image, without treating it as a template
UIImageRenderingModeAlwaysTemplate // Always draw the image as a template image, ignoring its color information
The default value of renderingMode
is UIImageRenderingModeAutomatic
. Whether the image will be tinted or not depends on where it’s being displayed as shown by the examples below:
The code below shows how easy it is to create an image with a given rendering mode:
UIImage *img = [UIImage imageNamed:@"myimage"];
img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
8. Usage of tintColor vs barTintColor
In iOS 7 you can tint your entire app with a given color or even implement color themes to help your app stand out from the rest. Setting the tint color of your app is as easy as using the new property tintColor
of UIView
.
Does that property sound familiar? it should — some classes such as UINavigationBar
, UISearchBar
, UITabBar
and UIToolbar
already had a property with this name. They now have a new property: barTintColor
.
In order to avoid getting tripped up by the new property, you should perform the following check if your app needs to support iOS 6 or earlier:
UINavigationBar *bar = self.navigationController.navigationBar;
UIColor *color = [UIColor greenColor];
if ([bar respondsToSelector:@selector(setBarTintColor:)]) { // iOS 7+
bar.barTintColor = color;
} else { // what year is this? 2012?
bar.tintColor = color;
}
9. Texture colors are gone

More victims of Jony Ive
Texture colors? Yup, they’re gone. You can’t create colors that represent textures anymore. According to the comments in UIInterface.h, -[UIColor groupTableViewBackgroundColor]
was supposed to be deprecated in iOS 6, but instead, it just doesn’t return the textured color it used to. However, the following colors have been deprecated in iOS 7:
+ (UIColor *)viewFlipsideBackgroundColor;
+ (UIColor *)scrollViewTexturedBackgroundColor;
+ (UIColor *)underPageBackgroundColor;
10. UIButtonTypeRoundRect has been deprecated in favor of UIButtonTypeSystem

Good bye, old friend.
One of your old friends from your beginnings in iOS development (and a popular control in many rapid prototypes) is now defunct: UIButtonTypeRoundRect
has been replaced by a new UIButtonTypeSystem
. Excuse the dust, but progress we must! :]
The Really Good News: New Features
What would a major release of iOS be without some new features? These new features have largely been well-received in the iOS community, and you may even find some novel ways to integrate them in your own apps!
11. Check which wireless routes are available
The ability to customize a video player (and friends) has evolved throughout the past few iOS versions. As an example, prior to iOS 6 you couldn’t change the AirPlay icon on a MPVolumeView
.
In iOS 7, you’re finally able to know if a remote device is available via AirPlay, Bluetooth, or some other wireless mechanism. This allows your app to behave appropriately, such as hiding an AirPlay icon when that service isn’t available on other devices.
The following two new properties and notifications have been added to MPVolumeView
:
@property (nonatomic, readonly) BOOL wirelessRoutesAvailable; // is there a route that the device can connect to?
@property (nonatomic, readonly) BOOL wirelessRouteActive; // is the device currently connected?
NSString *const MPVolumeViewWirelessRoutesAvailableDidChangeNotification;
NSString *const MPVolumeViewWirelessRouteActiveDidChangeNotification;
12. Get information about the cellular radio signal
Prior to iOS 7, detecting if a device was connected via WWAN or Wifi was possible using Reachability. iOS 7 takes it a step further and tells you exactly which kind of cell radio networking the device is connected to, such as Edge, HSDPA or LTE. This can be extremely useful to tailor the user experience to the speed of the network they are connected to, by making fewer network requests or downloading lower resolution images as appropriate.
This feature is part of the little known CTTelephonyNetworkInfo
, which is part of the CoreTelephony framework. iOS 7 also added the currentRadioAccessTechnology
property to this class, as well as the notification CTRadioAccessTechnologyDidChangeNotification
. There’s some new string constants as well to define the possible values such as CTRadioAccessTechnologyLTE
.
Here’s how you’d use this new feature in your app delegate:
@import CoreTelephony.CTTelephonyNetworkInfo; // new modules syntax!
@interface AppDelegate ()
// we need to keep a reference to the CTTelephonyNetworkInfo object, otherwise the notifications won't be fired!
@property (nonatomic, strong) CTTelephonyNetworkInfo *networkInfo;
@end
@implementation ViewController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// whatever stuff your method does...
self.networkInfo = [[CTTelephonyNetworkInfo alloc] init];
NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:CTRadioAccessTechnologyDidChangeNotification object:nil];
// whatever stuff your method does...
}
- (void)radioAccessChanged {
NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology);
}
@end
CTTelephonyNetworkInfo.h
to discover the other string constants for other wireless networks. As a note, currentRadioAccessTechnology
will return nil
if the device is currently not connected to a radio tower.
13. Sync passwords between user’s devices via iCloud
iOS 7 and Mavericks introduced iCloud Keychain to provide synchronization of passwords and other sensitive data via iCloud. This feature is available to developers via the kSecAttrSynchronizable
key in the Keychain attributes dictionary.
Since dealing directly with the Keychain is often a real pain, wrapper libraries provide an easy way to work with the Keychain – without the sharp edges. The SSKeychain wrapper library is probably the best-known one out there, and as an added bonus, it currently supports iCloud sync out of the box.
The code snippet below shows how you’d use SSKeychain:
#import <SSKeychain.h>
- (BOOL)saveCredentials:(NSError **)error {
SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
query.password = @"MySecretPassword";
query.service = @"MyAwesomeService";
query.account = @"John Doe";
query.synchronizable = YES;
return [query save:&error];
}
- (NSString *)savedPassword:(NSError **)error {
SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
query.service = @"MyAwesomeService";
query.account = @"John Doe";
query.synchronizable = YES;
query.password = nil;
if ([query fetch:&error]) {
return query.password;
}
return nil;
}
Don’t forget that CocoaPods is a quick and easy way to install SSKeychain.
14. Display HTML with NSAttributedString
Using Webviews in your apps can be frustrating at times; even if you’re only displaying a small amount of HTML content, Webviews can consume a lot of memory. iOS 7 makes this a lot easier, as you can create an NSAttributedString
from HTML with a few lines of code, as such:
NSString *html = @"<bold>Wow!</bold> Now <em>iOS</em> can create <h3>NSAttributedString</h3> from HTMLs!";
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:nil];
Now you’re free to use the NSAttributedString
on any UIKit object, such as a UILabel
or a UITextField
, as in the following code:
NSHTMLTextDocumentType
is just one of the possible values for the NSDocumentTypeDocumentAttribute
key. You can also use NSPlainTextDocumentType
, NSRTFTextDocumentType
or NSRTFDTextDocumentType
.
You can also create an HTML string from an NSAttributedString
as shown below:
NSAttributedString *attrString; // from previous code
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
NSData *htmlData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:options error:nil];
NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];
That should encourage you to use HTML more freely in your applications! You can learn more about attributed strings in iOS 6 by Tutorials.
15. Use native Base64
Base64 is a popular way to represent binary data using ASCII characters. Until now, developers were forced to use one of the many open source alternatives to encode and decode the Base64 content.
iOS 7 introduces the following four new NSData
methods to manipulate Base64-encoded data:
// From NSData.h
/* Create an NSData from a Base-64 encoded NSString using the given options. By default, returns nil when the input is not recognized as valid Base-64.
*/
- (id)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options;
/* Create a Base-64 encoded NSString from the receiver's contents using the given options.
*/
- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options;
/* Create an NSData from a Base-64, UTF-8 encoded NSData. By default, returns nil when the input is not recognized as valid Base-64.
*/
- (id)initWithBase64EncodedData:(NSData *)base64Data options:(NSDataBase64DecodingOptions)options;
/* Create a Base-64, UTF-8 encoded NSData from the receiver's contents using the given options.
*/
- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options;
These methods let you easily convert NSData
objects to and from Base64, as shown in the following example:
NSData* sampleData = [@"Some sample data" dataUsingEncoding:NSUTF8StringEncoding];
NSString * base64String = [sampleData base64EncodedStringWithOptions:0];
NSLog(@"Base64-encoded string is %@", base64String); // prints "U29tZSBzYW1wbGUgZGF0YQ=="
NSData* dataFromString = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSLog(@"String is %@",[NSString stringWithUTF8String:[dataFromString bytes]]); // prints "String is Some sample data"
If you need to support iOS 6 or earlier, you can use the following two deprecated methods that are now public:
/* These methods first appeared in NSData.h on OS X 10.9 and iOS 7.0. They are deprecated in the same releases in favor of the methods in the <code>NSDataBase64Encoding</code> category. However, these methods have existed for several releases, so they may be used for applications targeting releases prior to OS X 10.9 and iOS 7.0.
*/
- (id)initWithBase64Encoding:(NSString *)base64String;
- (NSString *)base64Encoding;
16. Check screenshots with UIApplicationUserDidTakeScreenshotNotification
Prior to iOS 7, apps like Snapshot or Facebook Poke used some pretty creative methods to detect when a user took a screenshot. However, iOS 7 provides a brand-new notification for this event: UIApplicationUserDidTakeScreenshotNotification
. Just subscribe to it as usual to know when a screenshot was taken.
UIApplicationUserDidTakeScreenshotNotification
is posted after the screenshot is taken. Currently there is no way to be notified before a screenshot is taken, which could be useful for hiding an embarrassing photo. Hopefully Apple adds an UIApplicationUserWillTakeScreenshotNotification
in iOS 8! :]
17. Implement multi-language speech synthesis
Wouldn’t be nice if you could make your app speak? iOS 7 introduces two new classes: AVSpeechSynthesizer
and AVSpeechUtterance
. Together, they can give your app a voice. The really interesting news? There is a huge selection of available languages are available — even ones that Siri doesn’t speak, like Brazilian Portuguese!
Using these two classes to provide speech synthesis in your apps is very easy. AVSpeechUtterance
represents what and how you want to say something. Then, AVSpeechSynthesizer
is used to say it, as shown in the code snippet below:
AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init];
AVSpeechUtterance *utterance =
[AVSpeechUtterance speechUtteranceWithString:@"Wow, I have such a nice voice!"];
utterance.rate = AVSpeechUtteranceMaximumSpeechRate / 4.0f;
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]; // defaults to your system language
[synthesizer speakUtterance:utterance];
That’s impressive — it only takes five lines of code to add speech to your app!
18. Use the new UIScreenEdgePanGestureRecognizer
UIScreenEdgePanGestureRecognizer
inherits from UIPanGestureRecognizer
and lets you detect gestures starting near the edge of the screen.
Using this new gesture recognizer is quite simple, as shown below:
UIScreenEdgePanGestureRecognizer *recognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleScreenEdgeRecognizer:)];
recognizer.edges = UIRectEdgeLeft; // accept gestures that start from the left; we're probably building another hamburger menu!
[self.view addGestureRecognizer:recognizer];
19. Realize Message.app behavior with UIScrollViewKeyboardDismissMode
Dismissing the keyboard while you scroll is such a nice experience in Messages.app. However, building this behavior into your own apps can be tough. Luckily, Apple added the handy property keyboardDismissMode
on UIScrollView
to make your life a little easier.
Now your app can behave like Messages.app just by changing a single property on your Storyboard, or alternatively by adding one line of code!
This property uses the new UIScrollViewKeyboardDismissMode
enum. The possible values of this enum are as follows:
UIScrollViewKeyboardDismissModeNone // the keyboard is not dismissed automatically when scrolling
UIScrollViewKeyboardDismissModeOnDrag // dismisses the keyboard when a drag begins
UIScrollViewKeyboardDismissModeInteractive // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss
Here’s the Storyboard property to change to dismiss the keyboard on scroll:
20. Detect blinks and smiles with CoreImage
iOS 7 adds two new face detection features to Core Image: CIDetectorEyeBlink
and CIDetectorSmile
. In plain English, that means you can now detect smiles and blinks in a photo! Unfortunately, that means that now iOS 7 can now get its feelings hurt.
Here’s an example of how you could use it in your app:
UIImage *image = [UIImage imageNamed:@"myImage"];
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
context:nil
options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
NSDictionary *options = @{ CIDetectorSmile: @YES, CIDetectorEyeBlink: @YES };
NSArray *features = [detector featuresInImage:image.CIImage options:options];
for (CIFaceFeature *feature in features) {
NSLog(@"Bounds: %@", NSStringFromCGRect(feature.bounds));
if (feature.hasSmile) {
NSLog(@"Nice smile!");
} else {
NSLog(@"Why so serious?");
}
if (feature.leftEyeClosed || feature.rightEyeClosed) {
NSLog(@"Open your eyes!");
}
}
21. Add links to UITextViews
Creating your own Twitter client just got easier on iOS 7 — now you’re able to add a link to an NSAttributedString
and invoke a custom action when it’s tapped.
First, create an NSAttributedString
and add an NSLinkAttributeName
attribute to it, as shown below:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"This is an example by @marcelofabri_"];
[attributedString addAttribute:NSLinkAttributeName
value:@"username://marcelofabri_"
range:[[attributedString string] rangeOfString:@"@marcelofabri_"]];
NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor],
NSUnderlineColorAttributeName: [UIColor lightGrayColor],
NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};
// assume that textView is a UITextView previously created (either by code or Interface Builder)
textView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;
textView.delegate = self;
That makes a link appear in the body of your text. However, you can also control what happens when the link is tapped by implementing the new shouldInteractWithURL:
method of the UITextViewDelegate
protocol, like so:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
if ([[URL scheme] isEqualToString:@"username"]) {
NSString *username = [URL host];
// do something with this username
// ...
return NO;
}
return YES; // let the system open this URL
}
Where to Go From Here?
Wow! That’s a ton of new features; some you may already be familiar with, but some of them are probably news to you, as they were to me.
If you want to learn even more about the changes under the hood in iOS 7, I recommend taking a look at the following resources:
- Apple: What’s New in iOS 7
- Apple: iOS SDK Release Notes for iOS 7
- Apple: iOS 6.1 to iOS 7.0 API Differences
- iOS 7 by Tutorials (our book!)
- NSHipster: iOS 7
- Essential iOS 7 Developer’s Guide by Double Encore
- iOS7-Sampler on GitHub
- Custom UIViewController Transitions by Ash Furrow
- Wrestling with Status Bars and Navigation Bars on iOS 7 by Jared Sinclair
Have you found any other hidden gems in iOS 7? If so, come join the forum discussion and share your discoveries with everyone!