Thứ Ba, 21 tháng 10, 2014

Introduction to iOS 8 App Extension: Creating a Today Widget

0 Flares 0 Flares ×

In iOS 8, Apple introduced app extensions which let you extend functionality beyond your app and make it available to users from other parts of the system like in other apps or from the Notification Center. iOS defines different types of extensions, each tied to an area of the system such as the keyboard, Notification Center, e.t.c. A system area that supports extensions is called an extension point. Below is a list of the extension points in iOS.

  • Today – Shows brief information and can allow performing of quick tasks in the Today view of Notification Center
  • Share – Share content with others or post to a sharing website
  • Action – Manipulate content in a host app
  • Photo Editing – Edit photos or videos within the Photos app
  • Document Provider – Provide access to and manage a repository of files
  • Custom Keyboard – Provide a custom keyboard to replace the iOS system keyboard

app-extension-today-featured

We will cover all these extension points in this and subsequent tutorials. With this article, we will focus on the Today Extension.

How Extensions Work

Before getting started with the Today Extensions, first let’s take a look at how extensions work as some of the concepts covered here will be used later in the tutorial.

To start off, extensions cannot be stand alone apps. They are delivered via the App Store as part of the app bundle. The app that the extension is bundled with is known as the container app while the app that invokes the extension is the host app. You can have more than one extension in a container app.

When an extension is running, it doesn’t run in the same process as the container app. Every instance of your extension runs as its own process. It is also possible to have one extension run in multiple processes at the same time. For instance, if let’s say, you have a sharing extension which is invoked in Safari. An instance of the extension, a new process, is going to be created to serve Safari. Now, if the user goes over to Mail and launches your share extension, a new process of the extension is created again. These two processes aren’t going to share address spaces.

An extension cannot communicate directly with its container app, nor can it enable communication between the host app and container app. However, indirect communication with its container app is possible via openURL() or via a shared data container like the use of NSUserDefaults to store data which both extension and container app can read and write to.

The Today Extension

Today extensions, also known as widgets, appear on the Today View of the Notification Center. They provide brief pieces of information to the user and they even allow some interaction, though limited, right from the Notification Center. You’ve seen these available in previous versions of iOS, for e.g. Reminders, Stocks and Weather. In iOS 8, third party apps can now have their own widgets.

We are going to see how to create a widget. So that we can focus on this and not on creating an app from scratch, I have provided a starter project that you can download here. The project is of a simple weather app which shows various weather information of a particular location. You will need an internet connection for the data to be fetched. To keep it simple, I didn’t include any GeoLocation functionality, and so user’s location is assumed to be Cupertino, CA. (You can easily modify the app to get weather data of your current location by using core location and placing the latitude and longitude values in the API url. A good tutorial on how to do this can be found here ).

The project comes with an API key that you can use, but should it stop working, you can register at forecast.io to get your own API key. Then replace the key in the url in the WeatherService.swift file

On running the app, you should see a view with weather details as shown below.

App Extension Demo - Starter Project

We are going to create a Today extension of the app that will show a brief summary of the weather in a view that can be expanded to reveal more data. We’ll also see how we can share data between the container app and extension. We’ll use this shared data to enable the user to set the location they want weather information on.

Embedded Frameworks and Code Reuse

Extensions are created in their own targets separate from the container app. This means that you can’t access common code files as you normally would in your project. To allow for code reuse between the container app and extension, you create an embedded framework which can be used across both targets. Place code that will need to be used by both the container app and extension in the framework to avoid code repetition.

In our app, both the extension and container app make a call to an API and update properties with the data from the API. Without using a framework, we would have to maintain two code bases with similar code, which would be inefficient and prone to errors.

To create a framework, select your project in The Project Navigator and add a new target by selecting Editor > Add Target.

Select iOS > Framework & Library > Cocoa Touch Framework from the window that appears. Set its name as WeatherDataKit and check that the language is Swift (we use Swift here, but you can select whichever language you prefer). Leave the rest of the options as they are and click Finish.

App Extension - Weather Data Kit

You will see a new target in the list of targets and a new group folder in the Project Navigator. When you expand the WeatherDataKit group, you will see WeatherDataKit.h. If you are using objective C or if you have any objective C files in your framework, then you will include all public headers of your framework here. We don’t have objective C code in our framework, so we won’t be editing this file.

You should note that app extensions are somewhat limited in what they can do and therefore not all Cocoa Touch APIs are available for use in extensions. For instance extensions cannot do the following:

  • Access the camera or microphone on an iOS device
  • Receive data using AirDrop (It can however send data using AirDrop)
  • Perform long-running background tasks
  • Use any API marked in header files with the NS_EXTENSION_UNAVAILABLE macro, or similar unavailability macro, or any API in an unavailable framework for example EventKit and HealthKit are unavailable to app extensions.
  • Access a sharedApplication object, and so cannot use any of the methods on that object

You can have the compiler let you know when you use disallowed APIs by selecting your framework from the list of targets. On the General tab, on the Deployment Info section, check Allow app extension API only.

app_extension_api

In the starter project, I had abstracted out common code into the files that are under the WeatherData folder group. Drag this folder into the WeatherDataKit group.

App Extension - Weather Group

Merely dragging a file from one target to another doesn’t make the file part of that target though. You have to change the file’s target membership yourself. To do this, select the WeatherDataViewController.swift file from the Project Navigator. Then open the File Inspector and change the files target in the Target Membership section by unchecking the Weather target and checking the WeatherDataKit target. Do the same for the WeatherService.Swift and WeatherData.swift files.

After doing this, there will be some error messages in ViewController.swift. Include the following import statement at the top of the file.

1
import WeatherDataKit

Build the app and it should work as before.

Creating the Widget

To create a widget, we’ll use the Today extension point template that Xcode provides. Select the project in the Project Navigator and add a new target by selecting Editor > Add Target. Select iOS > Application Extension > Today Extension and then click Next.

App Extension - Create Widget

Set the Product Name to Weather Widget and leave the rest of the settings as they are. Click Finish.

App Extension - Name Widget

You will get a prompt asking if you want to activate the Weather Widget scheme. Press Activate. Another Xcode scheme has been created for you and you can switch schemes by navigating to Product > Scheme and then selecting the scheme you want to switch to. You can also switch schemes from the Xcode toolbar.

From the list of available targets, select Weather Widget then on the General tab press the + button under Linked Frameworks and Libraries. Select WeatherDataKit.framework and press Add.

App Extension - Add Framework

With the framework linked, we can now implement the extension.

In the Project Navigator you will see that a new group with the widget’s name was created. This contains the extensions storyboard, view controller and property list file. The plist file contains information about the widget and most often you won’t need to edit this file, but an important key that you should be aware of is the NSExtension dictionary. This contains the NSExtensionMainStoryboard key with a value of the widget’s storyboard name, in our case “MainInterface”. If you don’t want to use the storyboard file provided by the template, you will have to change this value with the name of your storyboard file.

Open MainInterface.storyboard. You’ll see a simple view with a Hello World label. To run the extension, make sure the Weather Widget scheme is selected in Xcode’s toolbar and hit Run. A window will pop up for you to chose an app to run. This lets Xcode know which host app to run. Chose Today. With this selection, iOS will know to open Notification Center in the Today view, which in turn launches your widget. Notification Center is the Today Extension’s host app. Click Run and you should see the widget on your simulator’s/device’s Notification Center.

App Extension - Widget Initial Run

To display the weather data in our image, we first import the WeatherDataKit framework into our view controller. Add the following to the TodayViewController.swift file.

1
import WeatherDataKit

Then make the class a subclass of WeatherDataViewController by changing its declaration to the following.

1
class TodayViewController: WeatherDataViewController, NCWidgetProviding

Delete the Hello World label. Set the view’s height to 270 (Leave the width at 320).

Drag two labels and a button into the main view. Set the text of the labels as “Cupertino, CA” and “100” respectively and their color to Red: 66, Green: 145 and Blue: 211 (usually, you should select bright colors for your widget controls so that they are visible in the Notification Center’s dark blurry background). Delete the button’s title and set its image to ‘caret’. The caret.png file was included in the starter project. When you run the app, the image will not appear on the button. This is because the asset catalog has only been added to the container app’s target. To add it to the extension’s target, select Images.xcassets and in File Inspector, check Weather Widget. Leave the Weather target checked.

App Extension Demo - Asset Catalog

Drag a view into the main view and stretch it out so that its left and right and bottom sides hug the main view. Place the views roughly as shown below. You don’t need to be accurate, we will use Auto Layout for this. For visibility, I have left the view’s background color as white, but we will set it to clear color so that the whole widget blends with the Notification Center background.

App Extension - Initial Widget View

Select the view you just added, open the Identity Inspector and enter MoreDetailsContainer in the Label field of the Documents pane(you might need to expand the Documents pane to reveal the Label field). This gives the view a name and makes it easier to identify in the Document Inspector. Also set the views background color to clear color in the Attributes Inspector. You should have the following.

Widget without other data

The Apple Extensions Guide recommends widgets to be small and to have an adjustable height that allows users to show or hide information as appropriate. If your widget only shows brief information, this won’t be necessary but if it shows a lot of data, it is better to only make the most important information visible and allow the user the ability to expand the view to show more data. This is what we will do with our widget. The widget will only display the location and current temperature and on tapping the button with the caret image, the view will expand to reveal more weather data. We will set this data’s location and constraints relative to the MoreDetailsContainer view so that hiding and displaying this data will just be a matter of adjusting the MoreDetailsContainer view’s constraints.

Add the labels for the other data and place them on the MoreDetailsContainer view. Give them titles as shown below. You can set your own title, but note that I will be referring to them by their title if I need to e.g. summary label, Mostly Cloudy label, 100 label, e.t.c. I set the color of these labels to Light Text Color.

App Widget with Label Added

Select the Cupertino, CA label and then select Editor > Size to Fit Content. Do the same for the other labels that will be populated by the API call i.e. the 100, Mostly Cloudy, 0.65, 0.10 and 02:00 PM labels.

We’ll now add Auto Layout constraints to the view. Select the MoreDetailsContainer and then select Pin from the Auto Layout controls at the bottom of the Interface Builder canvas. Pin its Leading, Trailing and Bottom space to 0 and its Height to 220. Uncheck Constrain to margin checkbox. With this unchecked, there will be no padding around your view.

App Extension - Container View Constraint

Select the Cupertino, CA label and pin its Top and Leading space to 13 and 20 respectively. Make sure Constrain to margin is unchecked (for the rest of the article, have it unchecked for all the constraints we add)

cupertino_constraints

Select the caret button and pin its Top, Trailing and Bottom spaces to 10, 20, 10. Set its Width and Height to 30 and make sure both these checkboxes are selected.

caret_constraints

Select the 100 label and pin its Top and Trailing spaces to 13 and 20 respectively.

temperature constraint

Control-Drag from the Mostly Cloudy label to the Summary label and select Center Y. This will align the two labels centers. Do this for the other pairs of labels i.e. 0.65 and Humidity, 0.10 and Precipitation, e.t.c.

Select the Summary label and pin its Leading and Top spaces to 20 each. Also check its Width checkbox and set the value to 130.

Control drag from the Mostly Cloudy label to the Summary label and select Horizontal Spacing. Then select this constraint either from the view controller or from the document outline. In the Size Inspector, change the constraint’s Constant to 20.

modify_option_a

You can also select the constraint by selecting the Mostly Cloudy label, and then in Size Inspector in the Constraints pane, find the Leading Space to SUMMARY constraint and edit its Constant to 20.

modify_option_b

Control-Drag from the Humidity label to the Summary label and select Left. This will align its Leading position to the Summary label’s Leading position. Select that constraint and in the Size Inspector, make sure that its Constant is set to 0. Sometimes when you align the views Leading positions, a constant is set which will make them not properly aligned. Do the same for the Precipitation and Last Updated labels – Control-Dragging to the Summary label and selecting Left, then making sure the constraints Constant is 0.

Next select the Humidity label and Pin its Top space to 20. This sets its distance from the Summary label. Do the same for the Precipitation and Last Updated labels. Setting their distance from the conrol on top of them to 20 points.

Next Control-Drag from the 0.65 label to Mostly Cloudy label and select Left. Do the same for the 0.10 and 02:00 PM labels. This will align the labels starting point. Then select the main view and select Editor > Resolve Auto Layout Issues, under All Views, select Update Frames. Interface Builder will now show the constraints in their set positions.

Before setting up the labels to show real data from the API, run the app to make sure that everything is set correctly. You should see the following.

App Widget after auto layout

You’ll notice that the widget has a large left margin. If you want to fill the entire width of Notification Center, implement the following method. Place the following code in the TodayViewController class.

1
2
3
4
    func widgetMarginInsetsForProposedMarginInsets
        (defaultMarginInsets: UIEdgeInsets) -> (UIEdgeInsets) {
        return UIEdgeInsetsZero
    }

Run the project again and your widget will now fill the width of the Notification Center.

widget_width_fit

To implement the view’s Show More button, open the Assistant Header to reveal the TodayViewController.swift file next to the storyboard. Control Drag from the button to the view controller file and add an Outlet. Name it showMoreButton. Then Control-Drag again from the button and change the Connection to Action. Set the Type to UIButton and Name to showMore. You should have the following code added to the class.

1
2
3
4
    @IBOutlet weak var showMoreButton: UIButton!

    @IBAction func showMore(sender: UIButton) {
    }

We then need to create an outlet for the MoreDetailsContainer view’s height constraint. We’ll be changing its value to expand and shrink the view. In Document Outline, expand the MoreDetailsContainer and expand its constraints. Find the height constraint. It should be labelled Height – (220) – MoreDetailsContainer. Control-Drag from it to the view controller and create an Outlet. Name it ‘moreDetailsContainerHeightConstraint’. You should have the following.

1
    @IBOutlet weak var moreDetailsContainerHeightConstraint: NSLayoutConstraint!

Add the following property which will keep track of whether the view is expanded.

1
    var widgetExpanded = false

In viewDidLoad() add the following

1
    moreDetailsContainerHeightConstraint.constant = 0

This sets that view’s height constraints’ constant to 0, so that it’s hidden by default.

Modify the showMore() action method as follows.

1
2
3
4
5
6
7
8
9
10
11
    @IBAction func showMore(sender: UIButton) {
        if widgetExpanded {
            moreDetailsContainerHeightConstraint.constant = 0
            showMoreButton.transform = CGAffineTransformMakeRotation(0)
            widgetExpanded = false
        } else {
            moreDetailsContainerHeightConstraint.constant = 220
            showMoreButton.transform = CGAffineTransformMakeRotation(CGFloat(180.0 * M_PI/180.0))
            widgetExpanded = true
        }
    }

This checks to see if the view has been expanded, and sets the constraint back to 0, otherwise it sets it to 220, which is the height we had specified for the view. We also add an animation where the button caret faces down when the view is collapsed and points up when the view has been expanded.
With the interface set up, we should now connect the extension’s controls with the superview’s outlets. Open the extension’s storyboard file. In the Documents Outline, Control-Drag from the Today View Controller to the Cupertino, CA label and select locationLabel. Do the same for the 100 label and select temperatureLabel. Repeat for Mostly Cloudy(summaryLabel), 0.65(humidityLabel), 0.10(precipitationLabel) and 02:00 PM(timeLabel).

In TodayViewController.swift add the following property to the class.

1
    var latLong = "37.331793,-122.029584"

Add the following at the end of viewDidLoad()

1
2
3
4
5
    temperatureLabel.text = "--"
    summaryLabel.text = "--"
    timeLabel.text = "--"
    humidityLabel.text = "--"
    precipitationLabel.text = "--"

Then add the following method to the class. This makes the call to the API and updates the view.

1
2
3
4
5
6
7
8
9
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        getWeatherData(latLong, completion: { (error) -> () in
            if error == nil {
                self.updateData()
            }
        })
    }

Run the app and the widget should populate with real data.

App Weather Widget with Real Data

To enable the widget to update its view when it’s off-screen make the following changes to the `widgetPerformUpdateWithCompletionHandler`. The system takes a snapshot of the widget and periodically, will try to update it. If it updates successfully, the function calls the system-provided completion block with the NCUpdateResult.NewData enumeration. If the update wasn’t successful, then the existing snapshot is used.

1
2
3
4
5
6
7
8
9
10
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
        getWeatherData(latLong, completion: { (error) -> () in
            if error == nil {
                self.updateData()
                completionHandler(.NewData)
            } else {
                completionHandler(.NoData)
            }
        })
    }

Sharing NSUserDefaults between your app and a Today Extension

As stated earlier, a widget cannot directly communicate with a host app. Having them communicate may however be necessary for your project specification especially if you allow a user to configure some settings on the container app that will affect the extension. You can share data between extension and container app through NSUserDefaults.

We will see how to do this by enabling the user to select a location to view its weather information. The starter project contains a table view controller with a set number of locations the user can choose from. The location variety is hardcoded – this isn’t the best way to store data, but for this demo, it will do.

To get started, change your scheme with Product > Scheme > Weather. In the storyboard file, select the Main View of the View Controller Scene and select Editor > Embed In > Navigation Controller. This will place a navigation bar at the top of the view. Drag a Bar Button Item from the object library and place it on the right side of the navigation bar. Set its title to Edit. Control-Drag from this Bar Button Item to the table view controller and select the ‘show’ segue. Run the application and on tapping on the Edit button, you will see a table view with a list of locations. The My Location cell is selected by default. Selecting any other cell will move the check mark to it. We will save this data to NSUserDefaults so that the widget shows data of the selected location

Select Location

To enable reading from the same set of NSUserDefaults, select your main app target and choose the Capabilities tab. Switch on App Groups (you will require a developer account for this).

Create a new container and give it a unique name. According to the help, it must start with “group.”. I set the name to ‘group.com.appcoda.weather’.

Select the Weather Widget target and repeat the above process of switching on App Groups. Don’t create a new container for it though. Use the one you had created for the Weather target.

Open LocationTableViewController.swift and add the following property to the class.

1
    var defaults: NSUserDefaults = NSUserDefaults(suiteName: "group.com.appcoda.weather")

This will be used to read and write to NSUserDefaults. You must use the name of your group you created earlier as the suite name.

Modify the refresh() function as follows. Here we check to see if the user has set another location other than My Location as the location to track weather data. If they had done so, we set the value of selectedLocation to this new location.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    func refresh() {
        // hasSetLocation is set in NSUserDefaults to track whether the user has set any other location apart from My Location
        var hasSetOtherLocation: Bool? = defaults.boolForKey("hasSetLocation")
        if let hasSetLoc = hasSetOtherLocation {
            if (hasSetLoc == true) {
                selectedLocation = Location.fromRaw(defaults.integerForKey("location"))!
            }
        }

        for i in 0..<Location.NumLocationTypes.toRaw() {
            var cell:UITableViewCell = tableView(self.tableView, cellForRowAtIndexPath: NSIndexPath(forRow: i, inSection: 0))
            cell.accessoryType = selectedLocation.toRaw() == i ? UITableViewCellAccessoryType.Checkmark : UITableViewCellAccessoryType.None
        }
    }

Modify the tableView(tableView: didSelectRowAtIndexPath:) function as shown. We check for the selected location and if it isn’t My Location, then we save the location data to NSUserDefaults. These will be accessed by the container app and widget.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        selectedLocation = Location.fromRaw(indexPath.row)!

        // If other location is selected then set values that will be used in the API call and to populate the view, otherwise the default Cupertino values will be used
        if (selectedLocation != .MyLocation) {
            defaults.setInteger(indexPath.row, forKey: "location")
            defaults.setBool(true, forKey: "hasSetLocation")

            let locationData: (String, String) = getLocationData(selectedLocation)
            let locationDictionary = ["name": locationData.0, "latLong": locationData.1]

            defaults.setObject(locationDictionary, forKey: "locationData")
        } else {
            defaults.setBool(false, forKey: "hasSetLocation")
        }


        self.refresh()
    }

Below is the function that gets information on the selected location. As I mentioned before, I hardcoded the data for the demo. The function returns a Tuple that holds the location’s coordinates and name.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    func getLocationData(location: Location) -> (String, String) {

        switch location {
        case .MicrosoftHQ:
            return ("Redmond, WA", "51.461231,-0.9259415")
        case .FacebookHQ:
            return ("Menlo Park, CA", "37.484765,-122.148549")
        case .GoogleHQ:
            return ("Mountain View, CA", "37.422,-122.084058")
        default:
            // This will never be reached, but switch blocks have to be exhaustive
            return ("", "")
        }
    }

In ViewController.swift, add the following property to the class.

1
    var defaults: NSUserDefaults = NSUserDefaults(suiteName: "group.com.appcoda.weather")

Add the following function to the file. This will be called before the call to the API, to check if a different location than My Location was selected and set the latLong property with the coordinates of that location. It also updates the text for the locationLabel with the name of the location.

1
2
3
4
5
6
7
8
9
10
11
12
13
    func checkForSetLocation() {
        // hasSetLocation is set in NSUserDefaults to track whether the user has set any other location apart from My Location
        var hasSetOtherLocation: Bool? = defaults.boolForKey("hasSetLocation")
        if let hasSetLoc = hasSetOtherLocation {
            if (hasSetLoc == true) {
                let locationDict: NSDictionary? = defaults.objectForKey("locationData") as? NSDictionary
                if let dictionary = locationDict {
                    locationLabel.text = dictionary["name"] as? String
                    latLong = dictionary["latLong"] as String
                }
            }
        }
    }

Call this method before the call to the API.

1
2
3
4
5
6
7
8
9
10
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        checkForSetLocation()

        getWeatherData(latLong, completion: { (error) -> () in
            if error == nil {
                self.updateData()
            }
        })
    }

In TodayViewController add the following property to the class.

1
    var defaults: NSUserDefaults = NSUserDefaults(suiteName: "group.com.appcoda.weather")

Add the following function to the class. Notice that we are using similar code in the container app’s view controller and the widget’s view controller. If you find yourself repeating code in several places, then it might be best to place the code in a framework.

1
2
3
4
5
6
7
8
9
10
11
12
13
    func checkForSetLocation() {
        // hasSetLocation is set in NSUserDefaults to track whether the user has set any other location apart from My Location
        var hasSetOtherLocation: Bool? = defaults.boolForKey("hasSetLocation")
        if let hasSetLoc = hasSetOtherLocation {
            if (hasSetLoc == true) {
                let locationDict: NSDictionary? = defaults.objectForKey("locationData") as? NSDictionary
                if let dictionary = locationDict {
                    locationLabel.text = dictionary["name"] as? String
                    latLong = dictionary["latLong"] as String
                }
            }
        }
    }

Call the method before the API call in viewDidAppear()

1
2
3
4
5
6
7
8
9
10
11
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        checkForSetLocation()

        getWeatherData(latLong, completion: { (error) -> () in
            if error == nil {
                self.updateData()
            }
        })
    }

Do the same in widgetPerformUpdateWithCompletionHandler()

1
2
3
4
5
6
7
8
9
10
11
12
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
        checkForSetLocation()

        getWeatherData(latLong, completion: { (error) -> () in
            if error == nil {
                self.updateData()
                completionHandler(.NewData)
            } else {
                completionHandler(.NoData)
            }
        })
    }

Run the app, change locations and test that the widget does indeed update according to the set data.

What’s Coming Next

In this article we have looked at how to create and configure the Today Extension in your app. In the coming weeks we will look at the other 5 extensions available for iOS, so stay tuned.

For your reference, you can download the complete Xcode project from here.

Source : appcoda[dot]com

Thứ Hai, 20 tháng 10, 2014

iOS 8.1 Released To The Public, Download Now

ios-8-1-logo

Over the last few hours Apple released iOS 8.1 to the public. The new software version brings many features to life that Apple included in their iOS 8 demonstration over the summer, most notably, Apple Pay. In addition 8.1 also features iCloud Photo Library and continuity features.

Download iOS 8.1

Stores that work with Apple Pay

screen-shot-2014-10-20-at-9-27-56-am

screen-shot-2014-10-20-at-10-12-05-am

Jailbreaking iOS 8.1

Pretty much the same thing goes for 8.1 as did for 8.0.2. There has not been any reported progress on any new jailbreak. That means that it is almost absolutely fine to upgrade to 8.1 and still be ready for a future jailbreak.

Source : jailbreaknation[dot]com

iOS 8.1 Download Links

Download 8.1

You may also like to check out:

Source : jailbreaknation[dot]com

iOS 8.1 Download Released with Apple Pay, Camera Roll, Wi-Fi Fix, Bug Fixes, etc

ios-8-1

Apple has released iOS 8.1 for all compatible iPhone, iPad, and iPod touch devices. The update offers a variety of new features for mobile devices, and also resolves some of the bugs and issues that existed with prior versions of iOS 8. The iOS 8.1 update is recommended for all users to install on their respective devices.


iOS 8.1 features include Apple Pay support, which allows mobile payments to be made at participating retail providers from an iPhone using Visa, Mastercard, American Express, and major US banks; additionally, there is the inclusion of iCloud Photo Library, new Continuity features for Mac users with Yosemite, the re-inclusion of Camera Roll in the Photos app, and many additional changes and bug fixes. The complete release notes for iOS 8.1 can be found below.

It is not yet known if iOS 8.1 resolves all experienced issues with battery drain and iOS 8 wi-fi connection difficulties that were encountered by some individuals running iOS 8 and iOS 8.0.2, but preliminary reports are encouraging.

Download & Install iOS 8.1 with Software Update

The simplest way for most users to download and install the iOS 8.1 update is through the Over-The-Air software update mechanism directly on their devices. You must be on a wi-fi network for this to work. Download sizes for iOS 8.1 depend on the device being installed upon, ranging from as small as 160MB to as large as 2GB.

  1. Back up the iPhone, iPad, or iPod touch with iCloud or iTunes
  2. Open the “Settings” app and then “General” and to “Software Update”
  3. Choose “Download & Install” and let the update process complete

iOS 8.1 Download

Do not skip the back up process, it is rare but things occasionally go wrong and you do not want to lose your data.

The update may sit on “Preparing Update” for quite some time before beginning the actual installation. Just let it sit and complete the process.

iOS 8.1 can require a sizable amount of free storage space available to install. If you do not have free space available to complete the installation, you can follow these instructions and install it through iTunes, thereby circumventing the storage space limitation.

Install & Update to iOS 8.1 with iTunes

Users also have the option of connecting their iOS device to iTunes and installing the iOS 8.1 update that way. This is the best way to install the update if you don’t have storage available on the device to install iOS 8.1 with OTA. Again, be sure to back up to iTunes before you do this.

iOS 8.1 IPSW Firmware Download Links

Direct links to firmware downloads from Apple servers are available below. For best results, use Chrome or Safari and choose “Save As” when downloading the IPSW file, be sure it has a .ipsw file extension (it is not a zip or archive).

ios-8-1-ipsw

iOS 8.1 is officially compatible with iPhone 4S, iPhone 5, iPhone 5S, iPhone 6, iPhone 6 Plus, iPhone 5C, iPod touch 4th gen, iPad 2, iPad 3, iPad 4, iPad Air, iPad Air 2, iPad Mini, iPad Mini Retina, and iPad Mini Retina 2. Older devices do not support the update.

iOS 8.1 Release Notes

This release includes new features, improvements and bug fixes, including:

  • Apple Pay support for iPhone 6 and iPhone 6 Plus (U.S. only)
  • Photos includes new features, improvements and fixes
  • Adds iCloud Photo Library as a beta service
  • Adds Camera Roll album in Photos app and My Photo Stream album when iCloud Photo Library is not enabled
  • Provides alerts when running low on space before capturing Time Lapse videos
  • Messages includes new features, improvements and fixes
  • Adds the ability for iPhone users to send and receive SMS and MMS text messages from their iPad and Mac
  • Resolves an issue where search would sometimes not display results
  • Fixes a bug that caused read messages to not be marked as read
  • Fixes issues with group messaging
  • Resolves issues with Wi-Fi performance that could occur when connected to some base stations
  • Fixes an issue that could prevent connections to Bluetooth hands-free devices
  • Fixes bugs that could cause screen rotation to stop working
  • Adds an option to select between 2G, 3G or LTE networks for cellular data
  • Fixes an issue in Safari where videos would sometimes not play
  • Adds AirDrop support for Passbook passes
  • Adds an option to enable Dictation in Settings for Keyboards, separate from Siri
  • Enables HealthKit apps to access data in the background
  • Accessibility improvements and fixes
  • Fixes an issue that prevented Guided Access from working properly
  • Fixes a bug where VoiceOver would not work with 3rd party keyboards
  • Improves stability and audio quality when using MFi Hearing Aids with iPhone 6 and iPhone 6 Plus
  • Fixes an issue with VoiceOver where tone dialing would get stuck on a tone until dialing another number
  • Improves reliability when using handwriting, Bluetooth keyboards and Braille displays with VoiceOver
  • Fixes an issue that was preventing the use of OS X Caching Server for iOS updates

Some features may not be available for all countries or all areas.

Let us know if you install iOS 8.1 and whether it works great, or if you encounter any problems with the update that may require troubleshooting!

Source : osxdaily[dot]com

Chủ Nhật, 19 tháng 10, 2014

How to Delete an iCloud Account from an iPhone / iPad

iCloud For those of us who juggle between multiple iCloud accounts (which is really not recommended), you may need to remove an iCloud account associated with an iPhone or iPad some times. This is typically for situations where you need to swap in a different account, create a new iCloud login for some reason, or just change to another existent iCloud account that is better suited for a device. While iOS makes this process easy, but be sure you know why you would want to do this, otherwise you may encounter unanticipated problems.


Again, this is not recommended unless you know exactly why you’re deleting the iCloud account from your device. A single user with multiple iCloud and Apple ID’s is rarely a good idea. Doing this without reason can cause a variety of complications and errors, ranging from improper or missing iMessage delivery, loss of data syncing, inability to retrieve apps that are associated with an Apple ID and App Store account, the removal of expected iCloud backups, and even loss of files and iCloud data. In short, do not change your iCloud ID or remove your iCloud account from an iPhone, iPad, or iPod touch, unless you know exactly why you’re doing it and you understand the potential complications.

It’s a good idea to back up your iPhone / iPad before doing this just in case you mess something up.

Removing the Existing iCloud Account from iOS

First you’ll need to remove the existing iCloud account that is in use on the iOS device:

  1. Open the Settings app and go to “iCloud”
  2. Scroll down under all the settings to find “Delete Account” and tap on that
  3. Confirm the removal of the iCloud account from the device by tapping on “Delete”

Delete an iCloud Account from iOS

Note this removes all documents that are from iCloud from the phone or iPad, but not from iCloud itself. Whether or not you want to save contacts and calendar data is up to you.

Once the iCloud account has been removed from the device, you’re left with a blank iCloud login. Here you can either create a new Apple ID and accompanying iCloud account, or change to another iCloud account.

Switching to a Different iCloud Account in iOS

This effectively lets you change between iCloud accounts on any iOS device. Again, this is not a recommended procedure without knowing why you want to do this, since it can lead to a variety of problems. Note if you already changed an Apple Store ID to the proper ID, this is unnecessary as the setting will carry over.

  1. Follow the above steps to remove the existing iCloud account from the iOS device
  2. Enter the new / different iCloud Account credentials and log in as usual by tapping “Sign In”
  3. Choose the iCloud settings to use with the new account ID

Change an iCloud account in iOS

That’s it, the iCloud account associated with the iOS device has been switched.

Both of these tricks is helpful for when you erroneously use a single iCloud account for situations where different ones would be better, for example, using a single iCloud ID on spouses or kids unique iPhones – those are best served with individual iCloud accounts for each device. For your own personal devices, always try to use a single iCloud account and Apple ID, this insures continuity of app and iTunes purchases, and proper syncing of your files and data.

While this can remove iCloud and all related services from a device, this is not a replacement for resetting an iPhone to factory settings, which completely clears out all data and basically performs a fresh iOS installation. Obviously reseting everything isn’t going to be necessary if you simply need to change the login though, so use which is appropriate for the given situation.

Source : osxdaily[dot]com

Thứ Sáu, 17 tháng 10, 2014

How to Beta Test Your App Using TestFlight

0 Flares 0 Flares ×

Suppose you built an app and completed the testing of your app on a real device. So what’s next? Submit your app directly to App Store and make it available for download? Yes, you can if your app is a simple one. However, if you’re developing a high quality app, don’t rush to get your app out. I suggest you beta test the app before the actual release.

A beta test is a step in the cycle of a software product release. I know you’ve tested your app using the built-in simulator and on your own device. Interestingly, you may not be able to uncover some of the bugs, even though you’re the app creator. By going through beta test, you would be amazed at the number of flaws discovered at this stage. Beta testing is generally opened to a select number of users. They may be your potential app users, your blog followers, your colleagues, friends or even family members. The whole point of beta testing is to let a small group of real people get their hands on your app, test it and provide feedback. You want your beta tester to discover as many bugs as possible in this stage so that you can fix them before rolling out your app to the public.

You may be wondering how can you conduct a beta test for your app, how beta testers run your app before it’s available on App Store and how testers report bugs?

testflight-featured

In iOS 8, Apple released a new tool called TestFlight to streamline the beta testing. You may have heard of TestFlight before. It has been around for several years as an independent mobile platform for mobile app testing. In February 2014, Apple acquired TestFlight’s parent company, Burstly. With the official release of Xcode 6 and iOS 8, TestFlight is now integrated into iTunes Connect that allows you to invite beta testers using just their email addresses.

TestFlight allows you to arrange testing with external testers and internal users. Conceptually, both can be your testers at the beta testing stage. However, TestFlight refers internal users as members of your development team who have been assigned the Technical or Admin role in iTunes Connect. You’re allowed to invite up to 25 internal users to test your app. An external tester, on the other hand, is considered as an user outside your team and company. You can invite up to 1,000 users to beta test your app. There is a catch, though. Your app must be approved by Apple before you can invite your external testers for testing. This restriction doesn’t apply to internal users. Your internal users can begin beta testing once you upload your app to iTunes Connect.

In this tutorial, I will walk you through the beta test process using TestFlight. At the time of this writing, you can only arrange beta test for internal users only. So we will focus on beta testing with internal users. In general, you need to go through the below tasks to distribute an app for beta testing:

  • Create an app record on iTunes Connect.
  • Update the build string.
  • Archive and upload your app.
  • Manage beta testing in iTunes Connect.

Let’s get started.

Creating an App Record on iTunes Connect

Firstly, you need an app record on iTunes Connect before you can beta test an app. iTunes Connect is a web-based application for iOS developers to manage their apps sold on App Store. Assuming you have enrolled in the iOS Developer Program, you should be able to access iTunes Connect at http://itunesconnect.apple.com.

TestFlight - New App Record

Once signed into iTunes Connect, select My Apps and the + icon to create a new iOS app. You’ll be prompted to complete the following information:

  • App name – your app name appears on App Store
  • Primary language – the primary language of your app such as English
  • Bundle ID – the bundle ID of your app
  • Version – the version number of your app. If this is the first release, you can just put in
    1.0.
  • SKU – stands for Stock Keeping Unit. It can be anything you like. For example, your app
    name is “Awesome Food App”. You can use “awesome_food_app” as the SKU. You can use letters, numbers, hyphens, periods and underscores except space.

Once you click the Create button, you’ll proceed to another screen to fill in the details of your app.

App Video and Preview

TestFlight App Info

These are the preview screens for your app. In iOS 8, Apple lets you incorporate an app video in the preview. You need to provide at least one screenshot for 3.5- inch (640×960 pixels for portrait or 960×640 pixels for landscape), 4-inch (640×1136 pixels for portrait or 1136×640 pixels for landscape), 4.7-inch (750×1334 pixels) and 5.5-inch (1242×2208 pixels) devices. You can further refer to Apple’s iTunes Connect Developer guide for details.

App Description and URL

TestFlight - App Info

Next, fill in your app description and at at least one keyword that describes your app. It’s one of the most important elements affecting your app download. You may have heard of App Store Optimization (ASO). Keyword optimization is a part of ASO. I will not go into keyword optimization here. If you want to learn more about keyword optimization, you can refer to this article or just google ASO.

The support URL is mandatory. You can fill in the URL of your website or blog. If you don’t have one, register a website at wordpress.com.

General App Information

The next section is about the general information of your app. You need to upload the app icon. Remember the app icon (1024×1024 pixels) must be not contained any transparency element. Here is a sample of the app icon.

app icon

The icon has a square shape. After you upload the app icon to iTunes Connect, the icon will be converted to appear with rounded corners.

Next, fill in the version number (e.g. 1.0) and pick a category that best describes your app.

You need to give a rating for your app. Just click the Edit button next to Rating and complete the form. iTunes Connect generates a rating for your app based on your answers.

For the copyright field, you can just fill in your name or company preceded by the year the rights were obtained (e.g. 2014 AppCoda Limited).

If you want to list your app on Korean App Store, you need to provide the Trade Representative Contact Information.

App Review Information

You can skip the Build section and go straight to the App Review Information. Simply fill in your contact information.

The demo account field is optional. It is for those apps that require login.

Version Release
You’re allowed to release your app automatically or manually right once it has been approved by App Review. Just set it to Automatically release this version.

Finally click the Save button on the top right corner to save the changes.

If you didn’t miss any information, the “Submit for Review” should be enabled. That means your app record was successfully created on iTunes Connect.

Update Your Build String

Now go back to Xcode. You’re going to build your app and upload to iTunes Connect. But before that, review your project and make sure the version number matches what you entered in iTunes Connect.

In the project navigator, select the project and the target to display the project editor. Under the General tab, review the version field under Identity section. As this is the first build, set the Build field to 1.

testflight-24-7

Archiving and Uploading Your App

Before archiving your app, you should include the app icon and launch image in your Xcode project. The app icons are managed by the asset catalog. You should find the AppIcon set in Images.xcassets. To add an icon to the set, select an app icon in the Finder and drag it to the appropriate image well in the set viewer. You will need to provide various sizes of app icons to fit for different devices.

App Icon in image asset

Assuming you’ve included the app icon and launch screen in your Xcode project. You’re now ready to archive upload your app to iTunes Connect. It’s pretty easy to archive your app in Xcode 6. First, review the Archive scheme settings and ensure the build configuration sets to Release (instead of Debug).

TestFlight Scheme Setting

Go up to the Xcode menu. Choose Product > Scheme > Edit Scheme. Select Archive scheme and review the Build Configuration setting. The option should be set to Release.

Now you’re ready to archive your app. The Archive feature is disabled if you’re using a simulator. So first select iOS Device or your device name (if you have connected your iPhone to your Mac) from the Scheme toolbar menu. Then go up to the Xcode menu and choose Product > Archive.

Archive App

After archiving, your archive will appear in the Organizer. It’s ready to upload to iTunes Connect. But it’s best to go through the validation process to see if there are any issues. Just click the Validate button and then select your developer account. Xcode will then validate your archive.

App Upload - Organizer

If the validation is successful, you can click the Submit button to upload the archive to iTunes Connect.

TestFlight Upload Successful

Manage Beta Testing in iTunes Connect

Now that you’ve uploaded your build to iTunes Connect. Go back to http://itunesconnect.apple.com. Select My Apps and then your app.

You will find your app archive under PreRelease tab. To enable beta testing, flip the TestFlight Beta Testing to ON. The status will be changed from Inactive to Invite Testers.

Enable Testflight

Click Invite Testers and then click “Users and Roles” to invite your internal testers to try out the app. For existing users with Admin, Legal, or Technical role, you will see an Internal Tester switch. Flip it to ON to assign it as a tester.

Testflight Enable Beta Tester

Note: If the tester you want to invite is not in the list, you can click + icon to create an account for the user and set its role to Technical. Once saved, ask the tester to confirm his/her email so as to activate the account.

Then go back to your app. Under the Prerelease tab, select Internal Testers tab and you will see the tester that you just assigned. Click the checkbox of the tester and click Invite
button to send an invitation of the TestFlight Beta Testing. Your tester will receive an email of the invitation.

Testflight - send invitation

The tester just needs to click the Open TestFlight button and iOS automatically opens TestFlight app. The tester can then install your app for beta testing. If your tester does not have the TestFlight app installed, he/she will need to install it first.

Testflight app

For any future update of your beta app, your internal testers will always get the most recent build you uploaded.

Summary

Apple’s acquisition of TestFlight provides us with a powerful tool to easily beta test our apps. In this tutorial, I have walked you through the basics of TestFlight Beta Testing. If you’re building your next app, use the tool to invite your friends to test out your app before the official release. This is an important step to build a high quality app.

What do you think about the tutorial? Leave us comment and share your thought.

This is an excerpt of our Beginning iOS 8 Programming with Swift book. If you like the tutorial, check out our new book and support us.

Source : appcoda[dot]com

Thứ Năm, 16 tháng 10, 2014

iOS 8.1 Release Date Set for October 20

iOS 8.1 iOS 8.1 will be released for compatible iPhone, iPad, and iPod touch devices on Monday, October 20, according to Apple. The update will include new features like Apple Pay, the re-introduction of the Photos app Camera Roll, the ability to interact with Macs running OS X Yosemite, and the update is expected to include many bug fixes and solutions to some of the nuisances that arrived with the initial releases of iOS 8.


Typically Apple releases software updates in the morning, so users should expect to find the download sometime in the earlier half of the 20th. The release date for iOS 8.1 was announced by Apple at the October 16 iPad / Mac Event.

Separately, Mac users can find OS X Yosemite available now as a free download. Mac and iOS users who wish to use the Handoff and Continuity features will need to update their iPhone, iPad, and iPod touch devices to iOS 8.1, and their Macs to OS X Yosemite.

As usual, we’ll provide download links to the iOS 8.1 IPSW when they become available. Most users will be better off downloading the update through the Software Update mechanism on their devices, however.

All iPhone, iPad, and iPod touch models bought after Monday from Apple will pre-ship with iOS 8.1 installed.

All iDevice users who are currently running iOS 8 or iOS 8.0.2 are going to be strongly recommended to update to the iOS 8.1 release when possible, as it will not only include the new features, but it will presumably resolve most of the complaints and issues that have annoyed a select number of users.

As always, back up an the iPhone, iPad, or iPod touch to either iTunes or iCloud, or both, before installing software updates.

Source : osxdaily[dot]com