Local and Remote Notification Programming Guide

Local and Remote Notification Programming Guide 

《本地与远程通知编程指导》

Latest:2014.10.31

Remote Notification:iOS3.0 Mac OS v7.0

Local Notification:iOS4.0 Mac OS v

注:Remote Notification 即是 Push 


 本文有三部分:

1.大体介绍

2.本地和远程通知的深入学习

3.注册、部署、处理用户通知


§ 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

 

转载于:https://www.cnblogs.com/--yy/p/4161905.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值