Local and Remote Notification Programming Guide

Local and Remote Notification Programming Guide html

《本地與遠程通知編程指導》 ios

Latest:2014.10.31web

Remote Notification:iOS3.0 Mac OS v7.0編程

Local Notification:iOS4.0 Mac OS v安全

注:Remote Notification 便是 Push 服務器


 本文有三部分:網絡

1.大致介紹架構

2.本地和遠程通知的深刻學習併發

3.註冊、部署、處理用戶通知app


§ About Local Notifications and Remote Notifications  

Local notifications and remote notifications are the two types of user notifications. (Remote notifications are also known as push notifications.) Both types of user notifications enable an app that isn’t running in the foreground to let its users know it has information for them. The information could be a message, an impending calendar event, or new data on a remote server. When presented by the operating system, local and remote user notifications look and sound the same. They can display an alert message or they can badge the app icon. They can also play a sound when the alert or badge number is shown.

When users are notified that the app has a message, event, or other data for them, they can launch the app and see the details. They can also choose to ignore the notification, in which case the app is not activated.

Note: Remote notifications and local notifications are not related to broadcast notifications (NSNotificationCenter) or key-value observing notifications. 

關於本地和遠程推送的介紹:這是兩種不一樣類型的用戶通知,遠程通知又叫作推送通知。

目的爲了使app不在前臺運行的時候告知用戶該app有信息了,該信息能夠是消息,即將到來的日曆事件,或者是遠程服務器發出的新數據,是由操做系統iOS或者OSX來呈現的。本地和遠程通知顯示的效果是同樣的,能夠彈出信息,使app有帶數字的紅色角標,還有提示的聲音。

用戶能夠選擇運行app查看通知,也能夠在沒運行app以前在頂部通知中clear,忽略掉這些通知。

注意:本地通知和遠程通知與例如:廣播即通知中心,KVO通知是沒有關係的。

  • At a Glance 6

Local notifications and remote notifications have several important aspects you should be aware of. 

  • Local and Remote Notifications Solve Similar Problems 6

Only one app can be active in the foreground at any time. Many apps operate in a time-based or interconnected environment where events of interest to users can occur when the app is not in the foreground. Local and remote notifications allow these apps to notify their users when these events occur.

本地和遠程通知爲了解決一些類似的問題。好比:

在任什麼時候候只能有一個app在前臺運行着,許多的app基於時間和互聯的這種環境運行着,當app不在前臺的時候,它們能夠發生一些有趣的事件

因此本地和遠程通知容許當這些事件發生的時候通知用戶。

  RelevantChapter: LocalandPushNotificationsinDepth(page10) 

  • Local and Remote Notifications Are Different in Origination 6

Local and remote notifications serve different design needs. A local notification is scheduled and sent by the app itself. Remote notifications—also known as push notifications—arrive from outside a device or a Mac. They originate on a remote server—the app’s provider—and are pushed to apps on devices (via the Apple Push Notification service) when there are messages to see or data to download. 

  RelevantChapter: LocalandPushNotificationsinDepth(page10) 

本地和遠程通知在機制上是不一樣的。

本地和遠程分別是爲了避免同的需求而設計出來的:一個本地通知是被一個app應用本身安排部署併發起的,遠程通知即推送通知是從別的設備或者Mac發來的。

遠程通知來自一個遠程服務器-便是該app的服務器,有新消息或者新數據要下載的時候app的服務器經過APNs推送通知到app上面來。

  • You Register, Schedule, and Handle Both Local and Remote Notifications 7 

To have the system deliver a local notification at a later time, an app registers notification types (in iOS 8 and later), creates a local notification object (using either UILocalNotification or NSUserNotification), assigns it a delivery date and time, specifies presentation details, and schedules it for delivery. To receive remote notifications, an app must register notification types, then pass to its provider a device token it gets from the operating system.

When the operating system delivers a local notification or remote notification and the target app is not running in the foreground, it can present the notification to the user through an alert, icon badge number, or sound. If there is a notification alert and the user taps or clicks an action button (or moves the action slider), the app launches and calls a method to pass in the local-notification object or remote-notification payload. If the app is running in the foreground when the notification is delivered, the app delegate receives a local or remote notification.

In iOS 8 and later, user notifications can include custom actions. Also, location-based notifications can be sent whenever the user arrives at a particular geographic location.

  RelevantChapter: Scheduling,Registering,andHandlingNotifications(page14) 

註冊、安排部署、處理本地和遠程通知。

爲了在以後的某個時間讓操做系統發送一個本地通知,iOS 8以後,要註冊通知類型,建立本地通知對象用:UILocalNotification或者NSUserNotification,給對象設置發送日期和時間,制定好呈現的細節,調度它。

爲了接受到遠程通知,app必需要註冊通知類型,而後將從操做系統產生的device token傳給app服務器。

當操做系統發送一個本地通知或者遠程通知,此時目標app沒有在前臺運行,這個通知就能夠經過警告彈窗,app的徽標,聲音呈現給用戶,

若是用戶點擊了laert上面的action Button 或者滑動action Slider(鎖屏的時候),app會啓動程序,經過本地通知對象或者遠程通知的載體調用方法。

當通知到來的時候,app正在前臺運行,那麼appdelegate接受該通知。

注意:在iOS8以後,用戶通知能夠包括自定製的actions?而且,不管什麼時候用戶在到達一個特別的地理位置的時候,能夠發送基於位置的通知。

  • The Apple Push Notification Service Is the Gateway for Remote Notifications 7

Apple Push Notification service (APNs) propagates remote notifications to devices having apps registered to receive those notifications. Each device establishes an accredited and encrypted IP connection with the service and receives notifications over this persistent connection. Providers connect with APNs through a persistent and secure channel while monitoring incoming data intended for their client apps. When new data for an app arrives, the provider prepares and sends a notification through the channel to APNs, which pushes the notification to the target device. 

  RelatedChapter: ApplePushNotificationService(page34) 

APNs是遠程通知的網關。APNs將遠程通知傳給那些已經註冊去接受push通知的app的設備上。

每一個設備和APNs創建一個認證而且加密的IP鏈接,而且接受這個持久鏈接的通知。

app服務器經過一個持久和安全的通道鏈接APNs,當監聽到有想到app的數據到來時。

當有新數據到來的時候,app服務器將經過通道發送一個通知給APNs,這樣就完成了將通知push到app。

  • You Must Obtain Security Credentials for Remote Notifications 8

To develop and deploy the provider side of an app for remote notifications, you must get SSL certificates from Member Center. Each certificate is limited to a single app, identified by its bundle ID; it is also limited to one of two environments, one for development and one for production. These environments have their own assigned IP address and require their own certificates. You must also obtain provisioning profiles for each of these environments.

  RelatedChapter: ProvisioningandDevelopment(page49) 

若是要作遠程Push,你必需要爲該遠程Push獲取到安全認證。

爲了給app服務器那邊開發和配置遠程Push通知,必需要從Member Center中得到SSL受權證書。一個證書對應一個app,由應用的Bundle ID標示;

並且SSL證書在一下兩種環境下有限制:一個是開發環境,一個是生產環境。這兩個環境有他們本身分配的IP地址和本身的證書。

並且,你必須獲取這兩個環境的配置證書Provisioning profile。

  • The Provider Communicates with APNs over a Binary Interface 8

The binary interface is asynchronous and uses a streaming TCP socket design for sending remote notifications as binary content to APNs. There is a separate interface for the development and production environments, each with its own address and port. For each interface, you need to use TLS (or SSL) and the SSL certificate you obtained to establish a secured communications channel. The provider composes each outgoing notification and sends it over this channel to APNs.

APNs has a feedback service that maintains a per-app list of devices for which there were failed-delivery attempts (that is, APNs was unable to deliver a remote notification to an app on a device). Periodically, the provider should connect with the feedback service to see what devices have persistent failures so that it can refrain from sending remote notifications to them.

  RelatedChapters: ApplePushNotificationService(page34),ProviderCommunicationwithApple Push Notification Service (page 51) 

app服務器和APNs之間經過一個二進制接口進行通訊。

這個二進制接口是異步的,而且用了一個TCP 套接字socket設計用於把二進制的遠程通知發送給APNs,對開發和生產環境,各自都有一個獨立的接口,都有本身的地址和端口。

對於每一個接口,你須要用TLS或者你獲取到的SSL證書去創建一個安全的通訊通道,app服務器將遠程通知打包經過通道發送給APNs。

APNs有一個反饋服務:它維持了一個包含每一個app傳遞Push通知失敗的設備列表(就是APNs沒法傳遞給目標app的那些設備的列表),app服務器應該週期性的鏈接這個反饋服務,來查看推送失敗的那些設備,以即可以將Push通知發送給這些設備。

  • Prerequisites 8

App Programming Guide for iOS describes the high level patterns for writing iOS apps.

For local notifications and the client-side implementation of remote notifications, familiarity with app development for iOS is assumed. For the provider side of the implementation, knowledge of TLS/SSL and streaming sockets is helpful. 

先決條件:

對於客戶端方面:須要熟悉app開發。

對於app服務器方面的實現:須要知道關於TLS/SSL和socket的知識。

  • See Also 9 

The following documents provide background information:

App Distribution Quick Start teaches how to create a team provisioning profile in Xcode before you enable APNs.

App Distribution Guide describes how to perform a variety of tasks in Xcode and Member Center, such as configuring APNs.

Entitlement Key Reference documents the specific entitlements needed for an app to receive remote notifications.

You might find these additional sources of information useful for understanding and implementing local and remote notifications:

The reference documentation for UILocalNotification, UIApplication, and UIApplicationDelegate describe the local- and remote-notification API for client apps in iOS.

The reference documentation for NSApplication and NSApplicationDelegate Protocol describe the remote-notification API for client apps in OS X.

Security Overview describes the security technologies and techniques used for the iOS and OS X systems.

RFC 5246 is the standard for the TLS protocol.

Secure communication between data providers and Apple Push Notification service requires knowledge of Transport Layer Security (TLS) or its predecessor, Secure Sockets Layer (SSL). Refer to one of the many online or printed descriptions of these cryptographic protocols for further information.

For information on how to send push notifications to your website visitors using OS X, read Configuring Safari Push Notifications in Notification Programming Guide for Websites . 

如下文檔提供了本PG須要的一些背景知識:

App Distribution Quick Start 教你怎麼在Xcode中建立一個team provisioning profile,使得能用APNs。

App Distribution Guide 

Entitilement Key Reference

Reference:UILocalNotification, UIApplication, UIApplicationDelegate (NSApplication, NSApplicationDelegate Protocol)

Security Overview

RFC 5246

app服務器和APNs之間的安全通訊,須要對TLS(傳輸層安全)或者前身SSL(安全套接字層)有所瞭解,參閱有關這些加密協議描述的更多信息。

這一節爲About部分

下一節爲深刻學習本地和遠程通知

update:2014-12-14 14:50:11


 § Local and Remote Notifications in Depth

The essential purpose of both local and remote notifications is to enable an app to inform its users that it has something for them—for example, a message or an upcoming appointment—when the app isn’t running in the foreground. The essential difference between local notifications and remote notifications is simple:

  • Local notifications are scheduled by an app and delivered on the same device.

  • Remote notifications, also known as push notifications, are sent by your server to the Apple Push Notification service, which pushes the notification to devices.

講了本地通知與遠程通知的目的相同,手段不一樣。 

  • Local and Remote Notifications Appear the Same to Users

Users can get notified in the following ways:

  • An onscreen alert or banner

  • A badge on the app’s icon

  • A sound that accompanies an alert, banner, or badge

From a user’s perspective, both local and remote notifications indicate that there is something of interest in the app.

For example, consider an app that manages a to-do list, and each item in the list has a date and time when the item must be completed. The user can request the app to notify it at a specific interval before this due date expires. To effect this, the app schedules a local notification for that date and time. Instead of specifying an alert message, the app chooses to specify a badge number (1) and a sound. At the appointed time, iOS plays the sound ad displays the badge number in the upper-right corner of the icon of the app, such as illustrated in Figure 1-1.

Figure 1-1  An app icon with a badge number (iOS)

Application icon with a badge number

The user hears the sound and sees the badge and responds by launching the app to see the to-do item. Users control how the device and specific apps installed on the device should handle notifications. They can also selectively enable or disable remote notification types (that is, icon badging, alert messages, and sounds) for specific apps. 

本地和遠程通知顯示給用戶的方式是類似的:從用戶的角度來看,這兩種通知都預示着該app有些有趣的信息提示用戶

警告視圖或者banner

app的icon上有徽標

當以上二者出現的時候伴隨着提示音

官方例子:

一個app有一個to-do list 待辦事項列表,裏面的每一條要在一個日期時間到的時候完成。

  • Local and Remote Notifications Appear Different to Apps

If your app is frontmost when a local or remote notification arrives, the application:didReceiveRemoteNotification: orapplication:didReceiveLocalNotification:method is called on its app delegate. If your app is not frontmost or not running, you handle the notifications by checking the options dictionary passed to the application:didFinishLaunchingWithOptions: of your app delegate for either theUIApplicationLaunchOptionsLocalNotificationKey or UIApplicationLaunchOptionsRemoteNotificationKey key. For more details about handling notifications, see Scheduling, Registering, and Handling Notifications.

本地和遠程通知相對於App來講,是不同的。

當你的app正在前臺運行的時候,來了一條本地或者遠程的通知,會調用AppDelegated的方法:

對本地通知:application:didReceiveRemoteNotification: 或者對push:application:didReceiveLocalNotification:

當你的app在後臺或者沒有在運行的時候,你經過app delegate傳進的option即字典:方法是application:didFinishLaunchingWithOption: 

的key:UIApplicationLaunchOptionsLocalNotificationKey 和 UIApplicationLaunchOptionsRemoteNotificationKey

  • More About Local Notifications

Local notifications are ideally suited for apps with time-based behaviors, such as calendar and to-do list apps. Apps that run in the background for the limited period allowed by iOS might also find local notifications useful. For example, apps that depend on servers for messages or data can poll their servers for incoming items while running in the background; if a message is ready to view or an update is ready to download, they can handle the data as needed, and notify users if appropriate.

A local notification is an instance of UILocalNotification or NSUserNotification with three general kinds of properties:

  • Scheduled time. You must specify the date and time the operating system delivers the notification; this is known as the fire date. You can qualify the fire date with a specific time zone so that the system can make adjustments to the fire date when the user travels. You can also request the operating system to reschedule the notification at a regular interval (weekly, monthly, and so on).

  • Notification type. These properties include the alert message, the title of the default action button, the app icon badge number, a sound to play, and optionally in iOS 8 and later, a category of custom actions.

  • Custom data. Local notifications can include a user info dictionary of custom data.

Listing 2-9 describes these properties in programmatic detail. After an app has created a local-notification object, it can either schedule it with the operating system or present it immediately.

Each app on a device is limited to 64 scheduled local notifications. The system discards scheduled notifications in excess of this limit, keeping only the 64 notifications that will fire the soonest. Recurring notifications are treated as a single notification.

關於本地通知:

一個本地通知對象是UILocalNotification的實例,NSUserNotification是MacOX的

三種屬性:

  1.部署好時間:你必需要爲操做系統發送通知指定一個特定的日期和時間,屬性:fireDate

  2.通知的類型:這些屬性包括:彈出警告視圖的信息:alertBody 警告視圖的按鈕的標題或者鎖屏時的跑馬燈字:alertAction app的徽標:applicationIconBadgeNumber 提示音:soundName

  和iOS8以後,自定製的一些交互通知

  3.自定製data:本地通知能夠攜帶一個用戶的info,能夠將數據放進這個字典:userInfo

listing2-9中寫有代碼

在一臺設備上的一個app限定部署好的最多64個本地通知,系統將會拋掉多餘的本地通知。循環使用的通知會被當作是一個本地通知。

  • More About Remote Notifications

An iOS or Mac app is often a part of a larger application based on the client/server model. The client side of the app is installed on the device or computer; the server side of the app has the main function of providing data to its client apps, and hence is termed a provider. A client app periodically connects with its provider and downloads any data that is waiting for it. Email and social-networking apps are examples of this client/server model.

But what if the app is not connected to its provider or even running on the device or computer when the provider has new data for it to download? How does it learn about this waiting data? Remote (or push) notifications are the solution to this dilemma. A remote notification is a short message that a provider has delivered to the operating system of a device or computer; the operating system, in turn, can inform the user of a client app that there is data to be downloaded, a message to be viewed, and so on. If the user enables this feature (on iOS) and the app is properly registered, the notification is delivered to the operating system and possibly to the app. Apple Push Notification service (APNs) is the primary technology for the remote-notification feature.

Remote notifications serve much the same purpose as a background app on a desktop system, but without the additional overhead. For an app that is not currently running—or, in the case of iOS, not running in the foreground—the notification occurs indirectly. The operating system receives a remote notification on behalf of the app and alerts the user. Once alerted, users may choose to launch the app, which then downloads the data from its provider. If an app is running when a notification comes in, the app can choose to handle the notification directly.

As its name suggests, Apple Push Notification service uses a remote design to deliver remote notifications to devices and computers. A push design differs from its opposite, a pull design, in that the recipient of the notification passively listens for updates rather than actively polling for them. A push design makes possible a wide and timely dissemination of information with few of the scalability problems inherent with pull designs. APNs uses a persistent IP connection for implementing remote notifications.

Most of a remote notification consists of a payload: a property list containing APNs-defined properties specifying how the user is to be notified. For performance reasons, the payload is deliberately small. Although you may define custom properties for the payload, you should never use the remote-notification mechanism for data transport because delivery of remote notifications is not guaranteed. For more on the payload, see The Notification Payload.

APNs retains the last notification it receives from a provider for an app on a device; so, if a device or computer comes online and has not received the notification, APNs pushes the stored notification to it. A device running iOS receives remote notifications over both Wi-Fi and cellular connections; a computer running OS X receives remote notifications over both Wi-Fi and Ethernet connections.

Important: In iOS, Wi-Fi is used for remote notifications only if there is no cellular connection or if the device is an iPod touch. For some devices to receive notifications via Wi-Fi, the device’s display must be on (that is, it cannot be sleeping) or it must be plugged in. The iPad, on the other hand, remains associated with the Wi-Fi access point while asleep, thus permitting the delivery of remote notifications. The Wi-Fi radio wakes the host processor for any incoming traffic.

Sending notifications too frequently negatively impacts the device’s battery life—devices must access the network to receive notifications.

Adding the remote-notification feature to your app requires that you obtain the proper certificates from Member Center for either the iOS Developer Program or Mac Developer Program and then write the requisite code for the client and provider sides of the app. Provisioning and Development explains the provisioning and setup steps, and Provider Communication with Apple Push Notification Service and Scheduling, Registering, and Handling Notifications describe the details of implementation.

•關於遠程通知:

講了一下c/s架構,

 


這節是講的註冊,部署和處理通知部分

§ Registering, Scheduling, and Handling User Notifications

The are several tasks that an iOS or OS X app should do to register, schedule, and handle both local and remote notifications.

  • Registering for Notification Types in iOS

In iOS 8 and later, apps that use either local or remote notifications must register the types of notifications they intend to deliver. The system then gives the user the ability to limit the types of notifications your app displays. The system does not badge icons, display alert messages, or play alert sounds if any of these notification types are not enabled for your app, even if they are specified in the notification payload.

In iOS, use the registerUserNotificationSettings: method of UIApplication to register notification types. The notification types represent the user interface elements the app displays when it receives a notification: badging the app’s icon, playing a sound, and displaying an alert. If you don’t register any notification types, the system pushes all remote notifications to your app silently, that is, without displaying any user interface. Listing 2-1 shows how an app registers notification types.

Listing 2-1  Registering notification types

UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];   

Notice the use of the categories parameter in Listing 2-1. A category is a group of actions that can be displayed in conjunction with a single notification. You can learn more about categories in Using Notification Actions in iOS.

The first time you call the registerUserNotificationSettings: method, iOS presents a dialog that asks the user for permission to present the types of notifications the app registered. After the user replies, iOS asynchronously calls back to the UIApplicationDelegate object with the application:didRegisterUserNotificationSettings: method, passing aUIUserNotificationType object that specifies the types of notifications the user allows. Because the user can change their initial setting at any time, callcurrentUserNotificationSettings before you do any work preparing a notification for presentation.

In iOS 8 and later, calling registerUserNotificationSettings: applies to remote notifications as well as local notifications. Because doing so specifies the types of remote notifications the app displays, the registerForRemoteNotificationTypes: is deprecated in iOS 8. You can learn more about remote notifications in Registering for Remote Notifications.

• 在iOS中註冊通知類型

在iOS8+,app中須要使用本地或者遠程通知必須要註冊想要發送的通知類型。你能夠本身限定這些類型。

使用UIApplication的registerUserNotificationSettings:方法去註冊通知類型

注意categories的用法:categories是一個通知中的一組動做事件,參考 Using Notification Actions iOS

第一次調用registerUserNotificationSettings:方法,iOS會呈現一個對話框詢問用戶是否容許展現該app註冊的通知類型,當用戶迴應了,iOS異步的執行回調UIApplicationDelegate的application:didRegisterUserNotificationSettings: 傳進一個用戶在設置中容許的通知展現類型UIUserNotificationType

由於用戶是能夠隨時改變設置中的push類型,因此在你準備展現通知的時候,先調用currentUserNotificationSettings,獲取到用戶設置的容許類型

在iOS8+以後,本地和遠程通知都調用registerUserNotificationSettings:註冊,在iOS8以前註冊遠程通知的方法registerForRemoteNotificationTypes:被不推薦了,具體見下面的Registering for Remote Notification

  • Scheduling Local Notifications

In iOS, you create a UILocalNotification object and schedule its delivery using the scheduleLocalNotification: method of UIApplication. In OS X, you create anNSUserNotification object (which includes a delivery time) and the NSUserNotificationCenter is responsible for delivering it appropriately. (An OS X app can also adopt theNSUserNotificationCenterDelegate protocol to customize the behavior of the default NSUserNotificationCenter object.)

Creating and scheduling local notifications in iOS requires that you perform the following steps:

  1. In iOS 8 and later, register for notification types, as described in Registering for Notification Types in iOS. (In OS X and earlier versions of iOS, you need register only for remote notifications.) If you already registered notification types, call currentUserNotificationSettings to get the types of notifications the user accepts from your app.

  2. Allocate and initialize a UILocalNotification object.

  3. Set the date and time that the operating system should deliver the notification. This is the fireDate property.

    If you set the timeZone property to the NSTimeZone object for the current locale, the system automatically adjusts the fire date when the device travels across (and is reset for) different time zones. (Time zones affect the values of date components—that is, day, month, hour, year, and minute—that the system calculates for a given calendar and date value.)

    You can also schedule the notification for delivery on a recurring basis (daily, weekly, monthly, and so on).

  4. As appropriate, configure an alert, icon badge, or sound so that the notification can be delivered to users according to their preferences. (To learn about when different notification types are appropriate, see Notifications in iOS Human Interface Guidelines.)

    • An alert has a property for the message (the alertBody property) and for the title of the action button or slider (alertAction). Specify strings that are localized for the user’s current language preference.

    • To display a number in a badge on the app icon, use the applicationIconBadgeNumber property.

    • To play a sound, assign a sound to the soundName property. You can assign the filename of a nonlocalized custom sound in the app’s main bundle or you can assignUILocalNotificationDefaultSoundName to get the default system sound. A sound should always accompany the display of an alert message or the badging of an icon; a sound should not be played in the absence of other notification types.

  5. Optionally, you can attach custom data to the notification through the userInfo property. For example, a notification that’s sent when a CloudKit record changes includes the identifier of the record, so that a handler can get the record and update it.

  6. Optionally, in iOS 8 and later, your local notification can present custom actions that your app can perform in response to user interaction, as described in Using Notification Actions in iOS.

  7. Schedule the local notification for delivery.

    You schedule a local notification by calling scheduleLocalNotification:. The app uses the fire date specified in the UILocalNotification object for the moment of delivery. Alternatively, you can present the notification immediately by calling the presentLocalNotificationNow: method.

The method in Listing 2-2 creates and schedules a notification to inform the user of a hypothetical to-do list app about the impending due date of a to-do item. There are a couple things to note about it. For the alertBody and alertAction properties, it fetches from the main bundle (via the NSLocalizedString macro) strings localized to the user’s preferred language. It also adds the name of the relevant to-do item to a dictionary assigned to the userInfo property.

Listing 2-2  Creating, configuring, and scheduling a local notification

- (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore {
   NSCalendar
*calendar = [NSCalendar autoupdatingCurrentCalendar]; NSDateComponents *dateComps = [[NSDateComponents alloc] init]; [dateComps setDay:item.day]; [dateComps setMonth:item.month]; [dateComps setYear:item.year]; [dateComps setHour:item.hour]; [dateComps setMinute:item.minute]; NSDate *itemDate = [calendar dateFromComponents:dateComps]; UILocalNotification *localNotif = [[UILocalNotification alloc] init]; if (localNotif == nil) return; localNotif.fireDate = [itemDate dateByAddingTimeIntervalInterval:-(minutesBefore*60)]; localNotif.timeZone = [NSTimeZone defaultTimeZone]; localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in %i minutes.", nil), item.eventName, minutesBefore]; localNotif.alertAction = NSLocalizedString(@"View Details", nil); localNotif.soundName = UILocalNotificationDefaultSoundName; localNotif.applicationIconBadgeNumber = 1; NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey]; localNotif.userInfo = infoDict; [[UIApplication sharedApplication] scheduleLocalNotification:localNotif]; }

 

You can cancel a specific scheduled notification by calling cancelLocalNotification: on the app object, and you can cancel all scheduled notifications by callingcancelAllLocalNotifications. Both of these methods also programmatically dismiss a currently displayed notification alert. For example, you might want to cancel a notification that’s associated with a reminder the user no longer wants.

Apps might also find local notifications useful when they run in the background and some message, data, or other item arrives that might be of interest to the user. In this case, an app can present the notification immediately using the UIApplication method presentLocalNotificationNow: (iOS gives an app a limited time to run in the background).

In OS X, you might write code like that shown in Listing 2-3 to create a local notification and schedule it for delivery. Note that OS X doesn’t deliver a local notification if your app is currently frontmost. Also, OS X users can change their preferences for receiving notifications in System Preferences.

Listing 2-3  Creating and scheduling a local notification in OS X

//Create a new local notification NSUserNotification *notification = [[NSUserNotification alloc] init]; //Set the title of the notification notification.title = @"My Title"; //Set the text of the notification notification.informativeText = @"My Text"; //Schedule the notification to be delivered 20 seconds after execution notification.deliveryDate = [NSDate dateWithTimeIntervalSinceNow:20]; //Get the default notification center and schedule delivery [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:notification];

 •部署本地通知:

在iOS中建立和部署本地通知,如下是步驟:

1.在iOS8+以後,按照標題Register for Notification Types in iOS中註冊通知類型(在iOS8以前,你僅僅須要爲遠程通知註冊通知類型),若是你已經註冊了通知類型,調用currentUserNotificationSettings獲取用戶設置接收通知的類型

2.alloc init UILocalNotification

3.分配好操做系統發送本地通知的日期和時間,就是fireDate屬性

若是你爲當前通知設置了NSTimeZone的timeZone屬性,當設備時區改變或者重置了不一樣的時區時,系統自動的適應frie date

(time zone影響着date components 的值:例如day month,hour,year,和minute)

你也能夠爲通知部署基於循環發送的屬性

4.學習何時不一樣的通知類型是合適的,參考在 iOS Human Interface Guidelines裏面的Notification部分

展現的alertBody和alertAction要本地化爲用戶當前的語言設置

展現的Icon的徽標用applicationIconBadgeNumber屬性

播放提示音,屬性爲soundName,可使用非本地,自定製聲音,可使用默認的,不能光有提示音通知類型,提示音伴隨着別的通知類型播放

5.可選的

6.可選的, iOS8以後,你的本地通知能夠展示自定製的交互action 參見:Using Notification Actions in iOS

7.發佈這個本地通知

調用UIApplication的scheduleLocalNotification:方法在已經限定好的日期時間發送,

能夠當即展現通知,調用presentLocalNotificationNow:方法

二選一Alternatively

2-2的方法,建立和部署了一個本地通知,在一個即將到來的日期時間通知用戶的一個待辦事項列表的app。

這有一些注意事項:對於alertBody和alertAction屬性,經過NSLocalizaedString()本地化爲用戶設置的偏好語言,

也爲該待辦事項的通知添加一個name,給userInfo屬性

你能夠取消掉一個已經部署好的本地通知,用UIApplication的cancelLocalNotification:方法,你能夠取消掉全部已經部署好的本地通知,用UIApplication的cancelAllLocalNotifications方法

當app在後臺運行的時候,此時有新數據,消息到來,這種狀況下,app能夠用這個方法當即呈現這條通知

這句話我理解的場景:服務器返回一條消息給app,

if (數據到來){

建立NSLocalNotification

當即presentLocalNotification

或者在服務器返回數據的回調裏面 

- (void)callback {

建立NSLocalNotification

當即presentLocalNotification

這樣就能夠實時的通知用戶當前在後臺的app來消息了,「二狗子給你回信息了,去看看吧」

  • Registering for Remote Notifications

An app must register with Apple Push Notification service (APNs) to receive remote notifications sent by the app’s push provider. In iOS 8 and later, registration has four stages:

  1. Register the notification types your app supports using registerUserNotificationSettings:.

  2. Register to receive push notifications via APNs by calling your app’s registerForRemoteNotifications method.

  3. Store the device token returned to the app delegate by the server for a successful registration, or handle registration failure gracefully.

  4. Forward the device token to the app’s push provider.

(In iOS 7, instead of the first two steps, you register by calling the registerForRemoteNotificationTypes: method of UIApplication, and in OS X by calling theregisterForRemoteNotificationTypes: method of NSApplication.) The actions that take place during the registration sequence are illustrated by Figure 3-3 in Token Generation and Dispersal.

Device tokens can change, so your app needs to reregister every time it is launched.

If registration is successful, APNs returns a device token to the device and iOS passes the token to the app delegate in theapplication:didRegisterForRemoteNotificationsWithDeviceToken: method. The app passes this token, encoded in binary format, to its provider. If there is a problem in obtaining the token, the operating system informs the delegate by calling the application:didFailToRegisterForRemoteNotificationsWithError: method (or theapplication:didFailToRegisterForRemoteNotificationsWithError: method in OS X). The NSError object passed into this method clearly describes the cause of the error. The error might be, for instance, an erroneous aps-environment value in the provisioning profile. You should view the error as a transient state and not attempt to parse it.

iOS Note: If a cellular or Wi-Fi connection is not available, neither the application:didRegisterForRemoteNotificationsWithDeviceToken: method nor theapplication:didFailToRegisterForRemoteNotificationsWithError: method is called. For Wi-Fi connections, this sometimes occurs when the device cannot connect with APNs over port 5223. If this happens, the user can move to another Wi-Fi network that isn’t blocking this port or, on an iPhone or iPad, wait until the cellular data service becomes available. In either case, the device should be able to make the connection, and then one of the delegation methods is called.

 

By requesting the device token and passing it to the provider every time your app launches, you ensure that the provider has the current token for the device. Otherwise, pushes may not make their way to the user's device. If a user restores a backup to a device or computer other than the one that the backup was created for (for example, the user migrates data to a new device or computer), the user must launch the app at least once for it to receive notifications again. If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes. Moreover, never cache a device token and give that to your provider; always get the token from the system whenever you need it. If your app has previously registered, calling registerForRemoteNotifications results in the operating system passing the device token to the delegate immediately without incurring additional overhead. Also note that the delegate method may be called any time the device token changes, not just in response to your app registering or re-registering.

Listing 2-4 gives a simple example of how you might register for remote notifications in an iOS app. The code would be similar for a Mac app.

Listing 2-4  Registering for remote notifications

- (void)applicationDidFinishLaunching:(UIApplication *)app { // other setup tasks here....
    UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert; UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings]; [app.registerForRemoteNotifications]; // 這裏有一處錯誤! } // Delegation methods
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { const void *devTokenBytes = [devToken bytes]; self.registered = YES; [self sendProviderDeviceToken:devTokenBytes]; // custom method
} - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { NSLog(@"Error in registration. Error: %@", err); }

 

In your application:didFailToRegisterForRemoteNotificationsWithError: implementation, you should process that error object appropriately and make sure you disable any logic within your app that depends on receiving remote notifications. You don't want do any unnecessary processing within your app for notifications that aren't going to be coming in. Just gracefully degrade.

要能接受到遠程通知必需要註冊APNs,在iOS8以後有四個步驟:

1.註冊你app支持的通知類型,調用UIApplication的registerUserNotificationSettings:

2.註冊經過APNs接受遠程通知,調用UIApplication的registerForRemoteNotification:

3.調用註冊成功的回調,將device token存下,或者若是註冊失敗,調註冊失敗的回調中

4.將device token上傳給server

在iOS7中,1,2兩步只需調用UIApplication的registerForRemoteNotificationTypes:便可,~

device tokens能夠改變,因此你的app須要每次啓動的時候註冊一次 

若是註冊成功,APNs返回一個設備的device token 並其iOS將token傳給app delegate在下面這個方法中

application:didRegisterForRemoteNotificationWithDeviceToken:

app上傳這個token,編碼成二進制格式給服務器。

若是獲取device token失敗,操做系統調用方法通知代理application:didFailToRegisterForRemoteNotificationsWithError:

查看error分析註冊失敗的緣由

注意:若是沒有蜂窩網絡和Wi-Fi鏈接,application:didRegisterForRemoteNotificationsWithDeviceToken:和application:didFailToRegisterForRemoteNotificationsWithError:方法不會被調用,

鏈接APNs的端口5223

每一次啓動app,你每次註冊device token而後將其上傳給服務器,你就保證了服務器有設備當前的device token,不然pushes可能不會到達目標設備。若是用戶從備份中~~~

若是你的app以前已經註冊了push,調用registerForRemotNotifications,由於操做系統會當即將device token傳給代理,沒有額外的開銷。

注意:當device token改變的時候,代理方法可能隨時被調用,不只僅在app註冊push或者再次註冊的時候。

2-4 iOS中註冊遠程推送通知的例子

在application:didFailToRegisterForRemoteNotificationsWithError:實現中,你應該適當的處理錯誤對象,禁掉你app中對接受到遠程通知的所作的邏輯。

你不該該會想對沒有到來的通知作一些無必要的處理,just gracefully degrade (不知道該怎麼說)

  • Handling Local and Remote Notifications

Let’s review the possible scenarios that can arise when the system delivers a local notification or a remote notification for an app.

The notification is delivered when the app isn’t running in the foreground. In this case, the system presents the notification, displaying an alert, badging an icon, perhaps playing a sound, and perhaps displaying one or more action buttons for the user to tap.

The user taps a custom action button in an iOS 8 notification. In this case, iOS calls eitherapplication:handleActionWithIdentifier:forRemoteNotification:completionHandler: orapplication:handleActionWithIdentifier:forLocalNotification:completionHandler:. In both methods, you get the identifier of the action so that you can determine which button the user tapped. You also get either the remote or local notification object, so that you can retrieve any information you need to handle the action.

The user taps the default button in the alert or taps (or clicks) the app icon. If the default action button is tapped (on a device running iOS), the system launches the app and the app calls its delegate’s application:didFinishLaunchingWithOptions: method, passing in the notification payload (for remote notifications) or the local-notification object (for local notifications). Although application:didFinishLaunchingWithOptions: isn’t the best place to handle the notification, getting the payload at this point gives you the opportunity to start the update process before your handler method is called.

If the notification is remote, the system also calls application:didReceiveRemoteNotification:fetchCompletionHandler:.

If the app icon is clicked on a computer running OS X, the app calls the delegate’s applicationDidFinishLaunching: method in which the delegate can obtain the remote-notification payload. If the app icon is tapped on a device running iOS, the app calls the same method, but furnishes no information about the notification.

The notification is delivered when the app is running in the foreground. The app calls the UIApplicationDelegate method application:didReceiveLocalNotification: orapplication:didReceiveRemoteNotification:fetchCompletionHandler:. (If application:didReceiveRemoteNotification:fetchCompletionHandler: isn’t implemented, the system calls application:didReceiveRemoteNotification:.) In OS X, the system calls application:didReceiveRemoteNotification:.

An app can use the passed-in remote-notification payload or, in iOS, the UILocalNotification object to help set the context for processing the item related to the notification. Ideally, the delegate does the following on each platform to handle the delivery of remote and local notifications in all situations:

The delegate for an iOS app in Listing 2-5 implements the application:didFinishLaunchingWithOptions: method to handle a local notification. It gets the associatedUILocalNotification object from the launch-options dictionary using the UIApplicationLaunchOptionsLocalNotificationKey key. From the UILocalNotification object’suserInfo dictionary, it accesses the to-do item that is the reason for the notification and uses it to set the app’s initial context. As shown in this example, you might appropriately reset the badge number on the app icon—or remove it if there are no outstanding items—as part of handling the notification.

Listing 2-5  Handling a local notification when an app is launched

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; if (localNotif) { NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey]; [viewController displayItem:itemName]; // custom method
        app.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1; } [window addSubview:viewController.view]; [window makeKeyAndVisible]; return YES; }

 

The implementation for a remote notification would be similar, except that you would use a specially declared constant in each platform as a key to access the notification payload:

  • In iOS, the delegate, in its implementation of the application:didFinishLaunchingWithOptions: method, uses the UIApplicationLaunchOptionsRemoteNotificationKey key to access the payload from the launch-options dictionary.

  • In OS X, the delegate, in its implementation of the applicationDidFinishLaunching: method, uses the NSApplicationLaunchRemoteNotificationKey key to access the payload dictionary from the userInfo dictionary of the NSNotification object that is passed into the method.

The payload itself is an NSDictionary object that contains the elements of the notification—alert message, badge number, sound, and so on. It can also contain custom data the app can use to provide context when setting up the initial user interface. See The Notification Payload for details about the remote-notification payload.

Important: Delivery of remote notifications is not guaranteed, so you should not use the notification payload to deliver sensitive data or data that can’t be retrieved by other means.

One example of an appropriate usage for a custom payload property is a string identifying an email account from which messages are downloaded to an email client; the app can incorporate this string in its download user-interface. Another example of custom payload property is a timestamp for when the provider first sent the notification; the client app can use this value to gauge how old the notification is.

 

When handling remote notifications in your notification handling methods, the app delegate might perform a major additional task. Just after the app launches, the delegate should connect with its provider and fetch the waiting data.

Note: A client app should always communicate with its provider asynchronously or on a secondary thread.

 

The code in Listing 2-6 shows an implementation of the application:didReceiveLocalNotification: method which is called when app is running in the foreground. Here the app delegate does the same work as it does in Listing 2-5. It can access the UILocalNotification object directly this time because this object is an argument of the method.

Listing 2-6  Handling a local notification when an app is already running

- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif { NSString *itemName = [notif.userInfo objectForKey:ToDoItemKey]; [viewController displayItem:itemName]; // custom method
    app.applicationIconBadgeNumber = notification.applicationIconBadgeNumber - 1; }

 

If you want your app to catch remote notifications that the system delivers while it is running in the foreground, the app delegate must implement theapplication:didReceiveRemoteNotification:fetchCompletionHandler: method. The delegate should begin the procedure for downloading the waiting data, message, or other item and, after this concludes, it should remove the badge from the app icon. The dictionary passed in the second parameter of this method is the notification payload; you should not use any custom properties it contains to alter your app’s current context.

  • Using Notification Actions in iOS

In OS X and iOS versions prior to iOS 8, user notifications can have only one default action. In iOS 8 and later, user notifications can have additional custom actions. Two actions can be displayed on the lock screen, in a banner, and in Notification Center. In modal alerts, notifications can display up to four actions when the user taps the Options button. To use notification actions in your app, you need to register the actions, schedule a local notification or push a remote notification, and handle the action chosen by the user.

  • Registering Notification Actions

To use notification actions in your app, you must define the actions, group them into categories, and then register them with your app’s shared UIApplication instance.

To define a notification action, first you must create and initialize an instance of a notification action class, typically UIMutableUserNotificationAction. Then you define an identifier, passed back to your app when it handles the action, and a localized string displayed to the user on the action button. Next, you set the action’s activation mode to foreground if the action needs to interrupt the user or background if not. Finally, you declare whether the action is destructive, meaning its button displays red, and whether choosing the action requires the user to enter their passcode. Listing 2-7 illustrates these steps.

Listing 2-7  Defining a notification action

UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init]; // Define an ID string to be passed back to your app when you handle the action
acceptAction.identifier = @"ACCEPT_IDENTIFIER"; // Localized string displayed in the action button
acceptAction.title = @"Accept"; // If you need to show UI, choose foreground
acceptAction.activationMode = UIUserNotificationActivationModeBackground; // Destructive actions display in red
acceptAction.destructive = NO; // Set whether the action requires the user to authenticate
acceptAction.authenticationRequired = NO;

 

The activationMode property determines whether iOS launches your app in the foreground or background when the user responds to the notification. If you set it toUIUserNotificationActivationModeBackground, your app is given seconds to run. If the destructive property is NO, the action’s button appears blue; if it’s YES, the button is red. If you set the action’s authenticationRequired property to YES and the device is locked when the user responds to the notification, the user must enter a passcode when choosing the action. However, this does not unlock the device, so if your app needs to access files, make sure the files are in the right data protection class. When the value of the activationMode property isUIUserNotificationActivationModeForeground, the value of the authenticationRequired property is assumed to be YES regardless of its actual value.

For example, to configure actions for a calendar app, an Accept action needs no additional user interaction after the user taps the Accept button, so its activationMode can be background. Also, the Accept action is not destructive, so it doesn’t appear in red on the notification and lock screen, and it doesn’t need authentication because accepting an invitation is relatively harmless. As another example, a Trash action to delete a message in a Mail app also needs no further user interaction, so it can run in the background, but it is destructive, so itsdestructive property should be set to YES, and it requires authentication because you don’t want someone else deleting your messages. On the other hand, a Reply action requires user interaction, so the activation mode should be foreground. It’s not destructive, but the user must unlock the device because foreground actions always require authentication, regardless of the value in the authenticationRequired property.

After you have defined your actions, you need to group each of them into a category, which associates a type of notification with a set of related actions. For example, an Invite category could have Accept, Maybe, and Decline actions. A New mail category could have Mark as Read and Trash, and a Tagged category could have Like, Comment, and Untag actions. When crafting local or remote notifications for a user’s device, you specify the category that contains the actions you want to display with that notification. When the notification is displayed, iOS uses the category information to determine which buttons to display in the notification alert and to notify you of which action the user selected.

To group actions into a category, create and initialize an instance of a notification category class, typically UIMutableUserNotificationCategory. Then define an identifier for the category, which you include in local notifications and the push payload of remote notifications.

Next you add actions to the category and set their action context. There are two user notification action contexts: the default context, which supports four actions, and the minimal context, which displays two. The context relates to the part of the user interface in which the notification is presented—the lock screen only has room to display two actions, so the minimal context applies, whereas a modal alert has room for a full set of actions, and the default context applies. Listing 2-8 shows how these steps can be coded.

Listing 2-8  Grouping actions into categories

// First create the category
UIMutableUserNotificationCategory *inviteCategory = [[UIMutableUserNotificationCategory alloc] init]; // Identifier to include in your push payload and local notification
inviteCategory.identifier = @"INVITE_CATEGORY"; // Add the actions to the category and set the action context
[inviteCategory setActions:@[acceptAction, maybeAction, declineAction] forContext:UIUserNotificationActionContextDefault]; // Set the actions to present in a minimal context
[inviteCategory setActions:@[acceptAction, declineAction] forContext:UIUserNotificationActionContextMinimal];

 

The two setActions:forContext: messages in Listing 2-8 ensure that the actions are presented in the correct order in the default context, and that the most important actions are presented in a minimal context. That is, in a modal alert, the actions displayed are Accept, Maybe, and Decline (in that order), but on the lock screen the two actions displayed are Accept and Decline. If the second setActions:forContext: were not specified, only the first two actions of the default context would be displayed on the lock screen: Accept and Maybe.

After you define your notification action categories, you need to register them. You do this by grouping them together in a set, providing them to your user notification settings, and then registering those settings with your shared app instance. Listing 2-9 illustrates these steps.

Listing 2-9  Registering notification categories

NSSet *categories = [NSSet setWithObjects:inviteCategory, alarmCategory, ... UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:categories]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings];

 

The UIUserNotificationSettings class method settingsForTypes:categories: method is the same one shown in Listing 2-1 which passed nil for the categories parameter, and the notification settings are registered in the same way with the app instance. In this case, the notification categories, as well as the notification types, are included in the app’s notification settings.

  • Pushing a Remote Notification or Scheduling a Local Notification with Custom Actions

To show the notification actions that you defined, categorized, and registered, you must push a remote notification or schedule a local notification. In the remote notification case, you need to include the category identifier in your push payload, as shown in Listing 2-10. Support for categories is a collaboration between your iOS app and your push notification server. When your push server wants to send a notification to a user, it can add a category key with an appropriate value to the notification’s payload. When iOS sees a push notification with a category key, it looks up the categories that were registered by the app. If iOS finds a match, it displays the corresponding actions with the notification.

In iOS 8, the previous size limit of 256 bytes for a push payload has been increased to 2 kilobytes. See The Notification Payload for details about the remote-notification payload.

Listing 2-10  Push payload including category identifier

{ "aps" : { "alert" : "You’re invited!", "category" : "INVITE_CATEGORY", } }

 

In the case of a local notification, you create the notification as usual, then set the category of the actions to be presented, and finally, schedule the notification as usual, as shown in Listing 2-11.

Listing 2-11  Defining a category of actions for a local notification

UILocalNotification *notification = [[UILocalNotification alloc] init]; . . . notification.category = @"INVITE_CATEGORY"; [[UIApplication sharedApplication] scheduleLocalNotification:notification];

 

  • Handling Notification Actions

If your app is not running in the foreground, to handle the default action when a user just swipes or taps on a notification, iOS launches your app in the foreground and calls theUIApplicationDelegate method application:didFinishLaunchingWithOptions: passing in the local notification or the remote notification in the options dictionary. In the remote notification case, the system also calls application:didReceiveRemoteNotification:fetchCompletionHandler:.

If your app is already in the foreground, iOS does not show the notification. Instead, to handle the default action, it calls one of the UIApplicationDelegate methodsapplication:didReceiveLocalNotification: or application:didReceiveRemoteNotification:fetchCompletionHandler:. (If you don’t implementapplication:didReceiveRemoteNotification:fetchCompletionHandler:, iOS calls application:didReceiveRemoteNotification:.)

Finally, to handle the custom actions available in iOS 8, you need to implement at least one of two new methods on your app delegate,application:handleActionWithIdentifier:forRemoteNotification:completionHandler: orapplication:handleActionWithIdentifier:forLocalNotification:completionHandler:. In either case, you receive the action identifier, which you can use to determine what action was tapped. You also receive the notification, remote or local, which you can use to retrieve any information you need to handle that action. Finally, the system passes you the completion handler, which you must call when you finish handling the action. Listing 2-12 shows an example implementation that calls a self-defined action handler method.

Listing 2-12  Handling a custom notification action

- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier // either forLocalNotification: (NSDictionary *) notification or
                   forRemoteNotification: (NSDictionary *) notification completionHandler: (void (^)()) completionHandler { if ([identifier isEqualToString: @"ACCEPT_IDENTIFIER"]) { [self handleAcceptActionWithNotification:notification]; } // Must be called when finished
 completionHandler(); }

 

  • Using Location-Based Notifications

In iOS 8 and later, you can send the user a notification whenever they arrive at a particular geographic location. This feature uses Core Location and is implemented through simple API additions to the UILocalNotification class. You define Core Location region objects and attach them to a notification so that the notification fires when the user comes near, enters, or exits a region. You can make it so that the notification is presented only the first time that the user enters this region, or you could have the notifications fire continuously if that makes sense for your app.

  • Registering for Location-Based Notifications

Before you can schedule a location-based notification, you must register with Core Location. To register, create a CLLocationManager instance and set your app as the delegate on this manager. The delegate receives callbacks that tell your app whether it is allowed to track the user's location. Finally, you must send the location manager instance arequestWhenInUseAuthorization message, as shown in Listing 2-13. The first time your app calls this method, it displays an alert that asks the user to allow or disallow your app’s tracking of the user’s whereabouts. In addition to asking the user for permission for your app to access their location, the alert also displays some explanatory text that you provide, such as 「Enabling location tracking allows friends to see where you are.」 This explanatory string is required to use location services. Your app defines the string in its Info.plist file under theNSLocationWhenInUseUsageDescription key. If your app runs in locales with different languages, make sure you localize the string appropriately in your Info.plist strings file. If the user agrees to allow access, your app can track the user's location when your app is running in the foreground.

Listing 2-13  Getting authorization for tracking the user’s location

CLLocationManager *locMan = [[CLLocationManager alloc] init]; // Set a delegate that receives callbacks that specify if your app is allowed to track the user's location
locMan.delegate = self; // Request authorization to track the user’s location and enable location-based notifications
[locMan requestWhenInUseAuthorization];

 

Note that users may see location-based notification alerts even when your app is in the background or suspended. However, an app does not receive any callbacks until users interact with the alert and the app is allowed to access their location.

  • Handling Core Location Callbacks

At startup, you should check the authorization status and store the state information you need to allow or disallow location-based notifications. The first delegate callback from the Core Location manager that you must handle is locationManager:didChangeAuthorizationStatus:, which reports changes to the authorization status. First, check that the status passed with the callback is kCLAuthorizationStatusAuthorizedWhenInUse, as shown in Listing 2-14, meaning that your app is authorized to track the user’s location. Then you can begin scheduling location-based notifications.

Listing 2-14  Handling the Core Location authorization callback

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { // Check status to see if the app is authorized
    BOOL canUseLocationNotifications = (status == kCLAuthorizationStatusAuthorizedWhenInUse); if (canUseLocationNotifications) { [self startShowingLocationNotifications]; // Custom method defined below
 } }

 

Listing 2-15 shows how to schedule a notification that triggers when the user enters a region. The first thing you must do, as with a local notification triggered by a date or a time, is to create an instance of UILocalNotification and define its type, in this case an alert.

Listing 2-15  Scheduling a location-based notification

- (void)startShowingNotifications { UILocalNotification *locNotification = [[UILocalNotification alloc] init]; locNotification.alertBody = @「You have arrived!」; locNotification.regionTriggersOnce = YES; locNotification.region = [[CLCircularRegion alloc] initWithCenter:LOC_COORDINATE radius:LOC_RADIUS identifier:LOC_IDENTIFIER]; [[UIApplication sharedApplication] scheduleLocalNotification:locNotification]; }

 

When the user enters the region defined in Listing 2-15, assuming the app isn't running in the foreground, the app displays an alert saying: 「You have arrived!" The next line specifies that this notification triggers only once, the first time the user enters or exits this region. This is actually the default behavior, so it's superfluous to specify YES, but you could set this property to NO if that makes sense for your users and for your app.

Next, you create a CLCircularRegion instance and set it on the region property of the UILocalNotification instance. In this case we're giving it an app-defined location coordinate with some radius so that when the user enters this circle, this notification is triggered. This example uses a CLCircularRegion property, but you could also use CLBeaconRegion or any other type of CLRegion subclass.

Finally, call scheduleLocalNotification: on your UIApplication shared instance, passing this notification just like you would do for any other local user notification.

  • Handling Location-Based Notifications

Assuming that your app is suspended when the user enters the region defined in Listing 2-15, an alert is displayed that says: "You have arrived." Your app can handle that local notification in the application:didFinishLaunchingWithOptions: app delegate method callback. Alternatively, if your app is executing in the foreground when the user enters that region, your app delegate is called back with application:didReceiveLocalNotification: message.

The logic for handling a location-based notification is very similar for both the application:didFinishLaunchingWithOptions: and application:didReceiveLocalNotification:methods. Both methods provide the notification, an instance of UILocalNotification, which has a region property. If that property is not nil, then the notification is a location-based notification, and you can do whatever makes sense for your app. The example code in Listing 2-16 calls a hypothetical method of the app delegate namedtellFriendsUserArrivedAtRegion:.

Listing 2-16  Handling a location-based notification

- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification { CLRegion *region = notification.region; if (region) { [self tellFriendsUserArrivedAtRegion:region]; } }

 

Finally, remember that the application:didReceiveLocalNotification: method is not called if the user disables Core Location, which they can do at any time in the Settings app under Privacy > Location Services.

  • Preparing Custom Alert Sounds

For remote notifications in iOS, you can specify a custom sound that iOS plays when it presents a local or remote notification for an app. The sound files must be in the main bundle of the client app.

Custom alert sounds are played by the iOS system-sound facility, so they must be in one of the following audio data formats:

  • Linear PCM

  • MA4 (IMA/ADPCM)

  • µLaw

  • aLaw

You can package the audio data in an aiffwav, or caf file. Then, in Xcode, add the sound file to your project as a nonlocalized resource of the app bundle.

You may use the afconvert tool to convert sounds. For example, to convert the 16-bit linear PCM system sound Submarine.aiff to IMA4 audio in a CAF file, use the following command in the Terminal app:

afconvert /System/Library/Sounds/Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v

You can inspect a sound to determine its data format by opening it in QuickTime Player and choosing Show Movie Inspector from the Movie menu.

Custom sounds must be under 30 seconds when played. If a custom sound is over that limit, the default system sound is played instead.

  • Passing the Provider the Current Language Preference (Remote Notifications)

If an app doesn’t use the loc-key and loc-args properties of the aps dictionary for client-side fetching of localized alert messages, the provider needs to localize the text of alert messages it puts in the notification payload. To do this, however, the provider needs to know the language that the device user has selected as the preferred language. (The user sets this preference in the General > International > Language view of the Settings app.) The client app should send its provider an identifier of the preferred language; this could be a canonicalized IETF BCP 47 language identifier such as 「en」 or 「fr」.

Note: For more information about the loc-key and loc-args properties and client-side message localizations, see The Notification Payload.

Listing 2-17 illustrates a technique for obtaining the currently selected language and communicating it to the provider. In iOS, the array returned by the preferredLanguages property ofNSLocale contains one object: an NSString object encapsulating the language code identifying the preferred language. The UTF8String coverts the string object to a C string encoded as UTF8.

Listing 2-17  Getting the current supported language and sending it to the provider

NSString *preferredLang = [[NSLocale preferredLanguages] objectAtIndex:0]; const char *langStr = [preferredLang UTF8String]; [self sendProviderCurrentLanguage:langStr]; // custom method
}

The app might send its provider the preferred language every time the user changes something in the current locale. To do this, you can listen for the notification namedNSCurrentLocaleDidChangeNotification and, in your notification-handling method, get the code identifying the preferred language and send that to your provider.

If the preferred language is not one the app supports, the provider should localize the message text in a widely spoken fallback language such as English or Spanish.

 

參考:

文檔翻譯時間爲2012-01-28

http://wenku.baidu.com/view/765d930ab7360b4c2e3f64b8.html

相關文章
相關標籤/搜索