Ios9 3
Tutorial: How to test your app for IPv6 compatibility
At WWDC 2015 Apple announced the transition to IPv6-only network services in iOS 9. Starting June 1, 2016 all apps submitted to the App Store must support IPv6-only networking. Most apps will not require any changes because IPv6 is already supported by NSURLSession and CFNetwork APIs.
If your app uses IPv4-specific APIs or hard-coded IP addresses, you will need to make some changes.
What is IPv6?
IPv6 is short for “Internet Protocol Version 6”. IPv6 is the Internet’s next-generation protocol, designed to replace the current Internet Protocol, IP Version 4.
In order to communicate over the Internet, computers and other devices must have sender and receiver addresses. These numeric addresses are known as Internet Protocol addresses. As the Internet and the number of people using it grows exponentially, so does the need for IP addresses.
IPv6 allows more users and devices to communicate on the Internet by using bigger numbers to create IP addresses. Under IPv4, every IP address is 32 bits long, which allows 4.3 billion unique addresses. An example IPv4 address is:
172.16.254.1
In comparison, IPv6 addresses are 128 bits, which allow for approximately three hundred and forty trillion, trillion unique IP addresses. An example IPv6 address is:
2001:db8:ffff:1:201:02ff:fe03:0405
Enabling IPv6 test network from your Mac
One of the hidden features of OS X El Capitan is the ability to enable Internet Sharing to provide only IPv6 addresses. This feature was added to El Capitan to help developers ensure their apps are ready to work with IPv6. It uses NAT64, which facilitates communication between IPv6 and IPv4 hosts by using a form of NAT.
- Boot OS X 10.11
- Make sure your Mac is connected to the Internet, but not through Wi-Fi.
- Launch System Preferences from your Dock, LaunchPad, or the Apple menu.
- Press the Option key and click Sharing. Don’t release the Option key yet.
- Select Internet Sharing in the list of sharing services.
- Release the Option key.
- Select the Create NAT64 Network checkbox.
- Choose the network interface that provides your Internet connection, such as Thunderbolt Ethernet.
- Select the Wi-Fi checkbox.
- Click Wi-Fi Options, and configure the network name and security options for your network.
- Setting up local Wi-Fi network options
- Select the Internet Sharing checkbox to enable your local network.
- When prompted to confirm you want to begin sharing, click Start.
- Once sharing is active, you should see a green status light and a label that says Internet Sharing: On. In the Wi-Fi menu, you will also see a small, faint arrow pointing up, indicating that Internet Sharing is enabled. You now have an IPv6 NAT64 network and can connect to it from other devices in order to test your app.
Important: To ensure that testing takes place strictly on the local IPv6 network, make sure your test devices don’t have other active network interfaces. For example, if you are testing with an iOS device, make sure cellular service is disabled so you are only testing over Wi-Fi.
To test your IPv6 connectivity, you can visit Test your IPv6.
Testing Your App on the IPv6 Network
By enabling Create IPv6 Only Network, Internet Sharing will set up the following:
DNS64
NAT64
Use the NAT64 Network for app testing.
Make NAT64 testing part of your regular development process.
What breaks?
IPv4-only storage objects
IPv4-only APIs
IPv4-only usage of an API
Pre-Flight checks before connecting
– Checking to see if a device has an IPv4 address
– Checking to see if a device has a 0.0.0.0 address
Address-family agnostic code
Connect without preflight
– If connection succeeds, great
– If connection doesn’t succeed, handle the failure gracefully
Use higher-level networking frameworks
– NSURLSession and CFNetwork-layer APIs
RFC 4038 “Application Aspects of IPv6 Transition”
Connect-by-name APIs – Use DNS hostnames wherever possible instead of IP addresses.
IPv4 literals in NAT64+DNS64 networks
New for 10.11 and iOS 9
Use higher-level networking frameworks
– NSURLSession and CFNetwork-layer APIs
Client supplies IPv4 address Literal
– OS synthesizes IPv6 address
Tutorial: 3D Touch – Quick Actions in Swift
As of iOS 9, Apple has added quick actions to the app icon so users can deep link into an area of your app quicker. By pressing the app icon of the latest devices including the iPhone 6s and iPhone 6s Plus, the user obtains a set of quick actions. When the user selects a quick action, your app activates or launches and your app delegate object receives the quick action message.
Define Quick Actions
In your app’s Info.plist file create a UIApplicationShortcutItems array. This is where we define what the actions are, the title, subtitle, and short cut keys for each. Note that you can only have a max of 4 quick actions off the icon in your app.
UIApplicationShortcutItemType – A required string delivered to your app when the user invokes the corresponding quick action.
UIApplicationShortcutItemTitle – A required string displayed to the user on the Home screen as the name of the quick action.
UIApplicationShortcutItemSubtitle – An optional string that is displayed to the user on the Home screen, immediately below the corresponding title string.
UIApplicationShortcutItemIconType – An optional string specifying the type of an icon from the system-provided library.
You can find a full list of the icons Apple has in their asset library here:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationShortcutIcon_Class/index.html#//apple_ref/c/tdef/UIApplicationShortcutIconType
UIApplicationShortcutItemIconFile – An optional string specifying an icon image to use from the app’s bundle, or the name of an image in an asset catalog.
UIApplicationShortcutItemUserInfo – An optional, app-defined dictionary. One use for this dictionary is to provide app version information.
Below is an example of the ones I created for our sample app:
Next you can run your app and test to see if the quick actions are formatted the way you expected them to look. Note: You must develop on a device that supports 3D Touch. The simulator in Xcode does not support 3D Touch.
Handle the Short Cuts
Begin by adding the enum and properties we are going to need in the methods below. If you don’t want to use enums, then make sure your names match the UIApplicationShortcutItemType values entered in your Info.plist.
enum ShortcutIdentifier: String { case First case Second case Third case Fourth // MARK: Initializers init?(fullType: String) { guard let last = fullType.componentsSeparatedByString(".").last else { return nil } self.init(rawValue: last) } // MARK: Properties var type: String { return NSBundle.mainBundle().bundleIdentifier! + ".\(self.rawValue)" } } /// Saved shortcut item used as a result of an app launch, used later when app is activated. var launchedShortcutItem: UIApplicationShortcutItem?
Read in the UIApplicationShortcutItem that is selected by the User in the didFinishLaunchingWithOptions method. Here we are saving that value into launchedShortcutItem so can we handle it next.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. // If a shortcut was launched, display its information and take the appropriate action if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem { launchedShortcutItem = shortcutItem } return true }
The next method to get called is applicationDidBecomeActive, this method gets called after didFinishLaunchingWithOptions during the first launch of your app, or every time the user comes into your app while it’s still open in the background.
func applicationDidBecomeActive(application: UIApplication) { guard let shortcut = launchedShortcutItem else { return } handleShortCutItem(shortcut) launchedShortcutItem = nil }
When a user chooses one of the quick actions the app launches or resumes the app and calls the performActionForShortcutItem method below in your app delegate.
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -> Void) { let handledShortCutItem = handleShortCutItem(shortcutItem) completionHandler(handledShortCutItem) }
Lastly we need to handle the short cut and deep link the user into the proper view controller within our app.
func handleShortCutItem(shortcutItem: UIApplicationShortcutItem) -> Bool { var handled = false // Verify that the provided `shortcutItem`'s `type` is one handled by the application. guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else { return false } guard let shortCutType = shortcutItem.type as String? else { return false } let storyboard = UIStoryboard(name: "Main", bundle: nil) var vc = UIViewController() switch (shortCutType) { case ShortcutIdentifier.First.type: // Handle shortcut 1 vc = storyboard.instantiateViewControllerWithIdentifier("VC1") as! ViewController1 handled = true break case ShortcutIdentifier.Second.type: // Handle shortcut 2 vc = storyboard.instantiateViewControllerWithIdentifier("VC2") as! ViewController2 handled = true break case ShortcutIdentifier.Third.type: // Handle shortcut 3 vc = storyboard.instantiateViewControllerWithIdentifier("VC3") as! ViewController3 handled = true break case ShortcutIdentifier.Fourth.type: // Handle shortcut 4 vc = storyboard.instantiateViewControllerWithIdentifier("VC4") as! ViewController4 handled = true break default: break } // Display the selected view controller window!.rootViewController?.presentViewController(vc, animated: true, completion: nil) return handled }
You can grab the full source code for this tutorial. Note: Created using Xcode 7.2 (Swift 2).
tvOS Tutorial: Top Shelf in Swift
The top shelf is a content showcase area above the top row of apps on the Apple TV Home screen. The user can decide which apps are in the top row. When one of these apps is brought into focus, the top shelf displays featured content specific to that app.
It’s a unique opportunity for your app to highlight new, featured, or useful content and let the user jump directly to it. For example, when the iTunes TV Shows app is in focus, people see a row of featured shows. Focusing on and clicking a TV show goes right to the related product page in the app. Pressing the Play/Pause button on the remote while a show is in focus begins media playback for the show.
To begin, you’ll already need a tvOS app. Top Shelf is an extension to the tvOS app similar to a Today Widget and Apple Watch app to an iOS app, they are bundled together. You can follow the steps in this article on how to build an tvOS video app: tvOS Tutorial: Make a Video App in Swift. We’ll take this app and add the featured movies as our top shelf.
Static Image
At a minimum, every app must supply a single, static top shelf image that can be displayed when your app is in the top row of the Home screen and in focus. This image needs to be 1920px by 720px.
With the Assets folder, drag your image into the Top Shelf Image location, as seen below.
Sectioned Content Row
This layout style shows a single labeled row of sectioned content. It’s commonly used to highlight recently viewed content, new content, or favorites.
Content in the row is focusable, letting the user scroll through it at the desired speed. A label appears when an individual piece of content comes into focus, and small movements on the remote’s touch surface bring the focused image to life. A sectioned content row can be configured to show multiple labels, if desired.
This layout is templated and cannot be customized any further. It must contain a title, image and the title for the video will appear once the user has put it in focus. When a user taps on it it should deep link directly to the content within your app.
To create a sectioned content row, follow the steps below.
- Click File > New > Target
- Select “Application Extension” under tvOS and choose the “TV Services Extension”, and click “Next”.
- Name the extension, “TopShelf” is good.
- The Bundle Identifier is important. Since this is an extension it should be the same as your parent app. You can only add one more period “.” to the end to make it unique, i.e. com.brianjcoleman.Video-App.TopShelf and click “Finish”.
- A popup will appear, “Activate “TopShelf” scheme?”, you can click “Activate” on this. It will make the TopShelf target active so you can test it within Xcode.
- You’ll notice we now have a new folder in the Project Navigator with the ServiceProvider.swift and Info.plist file.
- To ensure we can access web servers for grabbing content, be sure to go into the Info.plist and add the following keys.
Enter the following code into ServiceProvider.swift
import Foundation import TVServices class ServiceProvider: NSObject, TVTopShelfProvider { override init() { super.init() } var topShelfStyle: TVTopShelfContentStyle { // Return desired Top Shelf style. return .Sectioned } var topShelfItems: [TVContentItem] { // Create an array of TVContentItems. let wrapperID = TVContentIdentifier(identifier: "shelf-wrapper", container: nil)! let wrapperItem = TVContentItem(contentIdentifier: wrapperID)! var ContentItems = [TVContentItem]() for (var i = 0; i < 8; i++) { let identifier = TVContentIdentifier(identifier: "VOD", container: wrapperID)! let contentItem = TVContentItem(contentIdentifier: identifier )! if let url = NSURL(string: "http://www.brianjcoleman.com/code/images/feature-\(i).jpg") { contentItem.imageURL = url contentItem.imageShape = .HDTV contentItem.title = "Movie Title" contentItem.displayURL = NSURL(string: "VideoApp://video/\(i)"); contentItem.playURL = NSURL(string: "VideoApp://video/\(i)"); } ContentItems.append(contentItem) } // Section Details wrapperItem.title = "Featured Movies" wrapperItem.topShelfItems = ContentItems return [wrapperItem] } }
Notice that we are defining the type of content to display in the topShelfStyle method. You can return either .Sectioned to display multiple items in the row on the screen at once (i.e. iTunes Movies) or .Inset which will display one large banner similar to the App Store.
The topShelfItems method should return the array of items, they are of type TVContentItem, which contain the following properties:
- imageURL - A URL giving the location of the image to be displayed for this content item.
- imageShape - The intended aspect ratio or shape of the content image.
Below are the three sizes available for .Sectioned content.
- title - The localized string title of the item.
- displayURL - A URL that causes the app which created this content item to display a description screen for the item. (type is NSURL)
- playURL - A URL that causes the app which created this content item to begin playing the item at the user's current position. (type is NSURL)
Lastly set the returned wrapper TVContentItem title to what you want the section header to be named.
Deep Linking
Top shelf layouts are a path to content that people care about most. Help them get to it quickly. Let users click a focused image to open your app and go right to the related content, or let them use the Play button on the remote to immediately start media playback or enter gameplay.
First setup your URL Scheme within the info.plist of your tvOS parent app.
The deep link URL will now be the URL scheme, plus any parameters you wish to pass through: VideoApp://video/1
You must provide data for both playURL and displayURL. Failing to provide both means that selecting a top shelf item does nothing. As soon as you provide a value for displayURL, selecting a video will immediately start opening your app. Just like iOS and Watch OS apps the first method that will get called in your App Delegate is openURL.
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { if url.host == nil { return true } let urlString = url.absoluteString let queryArray = urlString.componentsSeparatedByString("/") let query = queryArray[2] if query.rangeOfString("video") != nil { let videoIndexPathRow = queryArray[3] let deepLinkVideoIndexPathRow = videoIndexPathRow if deepLinkVideoIndexPathRow != "" { if let tabBarController = self.window!.rootViewController as? UITabBarController { let svc = tabBarController.viewControllers![0] as! MoviesViewController tabBarController.selectedIndex = 0 svc.setDeepLink(deepLinkVideoIndexPathRow) } } } return true }
The openURL method above reads in the URL passed from the top shelf. It then checks the query string for "video" as the key identifier to let us know that we want to play a video. This is helpful if you have multiple deep links for different features your app. Next we parse the rest of the URL to look for the row number selected so we know what video to play (this can be any unique identifier to let you know what video was selected). Then we direct the app to go to the MoviesViewController and call a new method named setDeepLink where we pass in the unique identifier and play the video.
func setDeepLink(videoIndexPathRow: String) { let playerVC = PlayerViewController() playerVC.playVideo() [self.presentViewController(playerVC, animated: true, completion: nil)] }
You'll notice that I am passing in the videoIndexPathRow but am not actually using it since this sample app doesn't have any actual data feeds, but you should pass something so you will need to key on a unique ID so you know what video to play. As soon as this method is called it starts the video player and plays the selected video.
You can grab the full source code for this tutorial.
Note: Created using Xcode 7.1 GM (tvOS & Swift 2).