iOS 10中的本地通知

本地通知是一种将通知发送给用户的好方法,而无需Internet连接或服务器端编程。 这些通知对于任何类型的“提醒类型的应用程序”都是完美的,并且自iOS 4发行以来就可用。如果您正在编程一段时间,我确定您已经熟悉UILocalNotification类,现在就熟悉iOS的发布10,我敢打赌,您和我一样高兴(这是非常讽刺的方式), UILocalNotification已过时。

好吧,新的更新随新的代码实现一起出现,作为开发人员,我们应该保持代码更新,对吗?

好的,让我们来聊聊吧,让我们构建一个非常简单的应用程序,它会使用新的UserNotifications Framework's UNNotificationRequest.提醒我们进行UserNotifications Framework's UNNotificationRequest. 首先在Xcode中创建一个新项目,然后在“链接框架和库”部分中添加UserNotifications Framework

转到您的AppDelegate.m文件,然后像这样导入框架…

现在,在didFinishLaunchingWithOptions:内部didFinishLaunchingWithOptions:复制并粘贴…

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
// Override point for customization after application launch.
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
//Show alert asking to go to settings and allow permission
}
}];
}
application.applicationIconBadgeNumber = 0;
return YES;
}

if语句基本上检查应用程序是否响应框架的特定选择器(如果不是),在这种情况下,可能不是针对iOS 10更新的应用程序。 UNUserNotificatinCenter为您的应用程序管理与通知有关的活动,我们使用此对象来请求授权,以便在本地(和远程)通知到达时与用户进行交互,现在运行该应用程序,并且您会看到询问授权的提示,不要不要忘记允许授权,否则将不会再有任何通知。

现在,转到您的viewController文件,让我们从UI开始,导入并添加UIButton作为这样的属性…

在ViewDidLoad内部,我们可以更改主视图的backgroundColor并添加UIButton,然后复制并粘贴…

 - (void)viewDidLoad { 
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:26.0/255.0 blue:56.0/255.0 alpha:1.0];
_button = [UIButton new];
_button.backgroundColor = [UIColor colorWithRed:221.0/255.0 green:27.0/255.0 blue:73.0/255.0 alpha:1.0];
[_button setTitle:@"SET TIMER" forState:UIControlStateNormal];
[_button addTarget:self action:@selector(generateLocalNotification:) forControlEvents:UIControlEventTouchUpInside];
_button.layer.cornerRadius = 20;
[self.view addSubview:_button];
}

现在,让我们在主视图中以编程方式布置UIButton,您当然可以在界面生成器中完成所有这些操作,但是,如果您是iOS的新手,并且想了解有关在内部布局视图的更多信息,我喜欢在代码中进行操作代码,请检查此链接。 将viewWillLayoutSubviews方法添加到您的文件中,然后复制并粘贴…

 - (void)viewWillLayoutSubviews { 
[super viewWillLayoutSubviews];

CGRect frame = _button.frame;
frame.size.height = 50;
frame.size.width = 200;
frame.origin.x = (self.view.frame.size.width - frame.size.width) /2;
frame.origin.y = (self.view.frame.size.height - frame.size.height) /2;
_button.frame = frame;
}

现在,您会收到一条警告,提示“未声明的选择器”,这意味着我们尚未声明此方法,让我们开始吧,在其中,我们添加实现以在用户点击按钮时添加本地通知,复制和粘贴…

 - (void)generateLocalNotification:(id)sender { 

UNMutableNotificationContent *localNotification = [UNMutableNotificationContent new];
localNotification.title = [NSString localizedUserNotificationStringForKey:@"Time for a run!" arguments:nil];
localNotification.body = [NSString localizedUserNotificationStringForKey:@"BTW, running late to happy hour does not count as workout" arguments:nil];
localNotification.sound = [UNNotificationSound defaultSound];
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10 repeats:NO];

localNotification.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] +1);

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"Time for a run!" content:localNotification trigger:trigger];

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
NSLog(@"Notification created");
}];
}

这是什么 要生成通知,我们需要首先创建一个UNMutableNotificationContent ,它是为通知提供可编辑内容的对象,设置其属性的标题,主体,声音(可以自定义),并为badge属性传递值UIApplication的applicationIconBadgeNumber属性加1。然后创建UNTimeIntervalNotificationTrigger的实例,此对象在指定的时间后触发本地通知的传递,在这种情况下,我们将其设置为10秒。 下一步是使用UNNotificationRequest创建一个请求,并使用方法addNotificationRequest:withCompletionHandler UNNotificationRequest将其添加到UNUserNotificationCenter的实例中,现在运行该应用程序,按一下按钮,然后立即按CMD + SHIFT + H转到模拟器首页,等待…并,图鲁鲁! 您将看到带有红色数字1的应用程序的红色徽章图标和弹出的横幅!

如果打开该应用程序,然后再按CMD + SHIFT + H再次将其发送到前台,则会注意到该徽章仍在显示您有通知,一个简单的解决方法是在applicationWillEnterForeground:添加以下代码applicationWillEnterForeground:在您的AppDelegate.m ,就像这样……

好的,这很酷,但是如果我们可以在用户点击通知时实际做一些事情,并且即使在用户使用应用程序时也显示通知,这会更好,为此,我们将实现UNUserNotificationCenterDelegate协议。 顺便说一句,如果您不熟悉授权,我建议检查与该主题相关的Apple文档,首先添加这样的协议…

然后将此行添加到UNUserNotificationCenter实例上方的generateLocalNotification方法中……

center.delegate = self;

现在,让我们实现委托方法! 但是首先让我们创建一种显示警报的方法,该警报将向用户显示Notification的内容,然后复制并粘贴…

 - (void)takeActionWithLocalNotification:(UNNotification *)localNotification { 

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:localNotification.request.content.title message:localNotification.request.content.body preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"ok");
}];
[alertController addAction:ok];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alertController animated:YES completion:^{
}];
});
}

此方法将UNNotification作为参数,并使用它来显示通知的内容,在本例中为标题和正文。 不要忘记在主队列中显示警报the

首先,我将实现委托方法willPresentNotification:withCompletionHandler:在使用应用程序时向用户显示通知……是的,再复制并粘贴一次🙂

 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { 

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Notification alert" message:@"This app just sent you a notification, do you want to see it?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ignore = [UIAlertAction actionWithTitle:@"IGNORE" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"ignore");
}];
UIAlertAction *see = [UIAlertAction actionWithTitle:@"SEE" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

[self takeActionWithLocalNotification:notification];
}];

[alertController addAction:ignore];
[alertController addAction:view];

[self presentViewController:alertController animated:YES completion:^{
}];
}

在此方法内部,我们创建了一个警报,该警报将告诉我们我们刚收到通知,如果希望查看它,您可以看到我们正在使用之前创建的方法,并且现在将通知作为参数传递运行该应用程序,按按钮,然后等待提示,然后按“ SEE”,就可以开始运行了!

最后,我将向您展示如何使用委托方法didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:当用户点击横幅时执行操作,为此,我们将重用在开始时创建的方法takeActionWithLocalNotification:接受UNNotification对象作为参数,然后复制并粘贴…

 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { 
[self takeActionWithLocalNotification:response.notification];
}

现在,运行该应用程序,按按钮,然后按CMD + SHIFT + H将其发送到前台,等待横幅,并在其上出现点击后,该应用程序将打开,向您显示带有通知内容的警报。

就是这样,您可以在此方法内实施任何操作,例如在这种情况下,显示提醒。
但是等一下,别说了,我能感觉到你的表情,你是对的。 最好让用户决定多长时间进行一次运动,对不对? 因此,我们添加一个UIDatePicker来完成该任务。

开始添加这些属性…

 @property (nonatomic, assign) NSTimeInterval countDownInterval; 
@property (nonatomic, strong) UIDatePicker *timePicker;

替换该实现的viewDidLoad。

 - (void)viewDidLoad { 
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:26.0/255.0 blue:56.0/255.0 alpha:1.0];

_timePicker = [UIDatePicker new];
_timePicker.backgroundColor = [UIColor clearColor];
_timePicker.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
[_timePicker addTarget:self action:@selector(userSelectTime:) forControlEvents:UIControlEventValueChanged];
[_timePicker setValue:[UIColor colorWithRed:253.0/255.0 green:210.0/255.0 blue:5.0/255.0 alpha:1.0] forKey:@"textColor"];
_timePicker.datePickerMode = UIDatePickerModeCountDownTimer;
dispatch_async(dispatch_get_main_queue(), ^{
_timePicker.countDownDuration = _countDownInterval;
});
[self.view addSubview:_timePicker];

_button = [UIButton new];
_button.backgroundColor = [UIColor colorWithRed:221.0/255.0 green:27.0/255.0 blue:73.0/255.0 alpha:1.0];
[_button setTitle:@"SET TIMER" forState:UIControlStateNormal];
[_button addTarget:self action:@selector(generateLocalNotification:) forControlEvents:UIControlEventTouchUpInside];
_button.layer.cornerRadius = 20;
_button.alpha = 0.3;
_button.userInteractionEnabled = NO;
[self.view addSubview:_button];
}

我不会对此进行详细介绍,因为本文的核心是如何使用本地通知,但是乍一看,我们只是添加了一个UIDatePicker,其方法是当选择器中的值发生更改时将更新“ countDownInterval”属性。 同样,我们将按钮的alpha更改为0.3,并将用户交互设置为禁用。 现在,让我们在viewWillLayoutSubviews方法中更改实现,替换该实现……

 - (void)viewWillLayoutSubviews { 
[super viewWillLayoutSubviews];

CGRect frame = _timePicker.frame;
frame.size.height = _timePicker.intrinsicContentSize.height;
frame.size.width = self.view.frame.size.width;
frame.origin.x = 0;
frame.origin.y = (self.view.frame.size.height - frame.size.height) /2;
_timePicker.frame = frame;

frame = _button.frame;
frame.size.height = 50;
frame.size.width = 200;
frame.origin.x = (self.view.frame.size.width - frame.size.width) /2;
frame.origin.y = ((CGRectGetMaxY(self.view.frame) - CGRectGetMaxY(_timePicker.frame)) - frame.size.height) / 2 + CGRectGetMaxY(_timePicker.frame);
_button.frame = frame;

}

现在,在方法generateLocalNotification:找到方法triggerWithTimeInterval:然后将我们的全局属性“ countDownInterval”作为这样的参数传递…

 UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:_countDownInterval repeats:NO]; 

最后,让我们声明方法userSelectTime:如果“ countDownInterval”大于2分钟(在这种情况下),此方法将更新“ countDownInterval”属性并启用UIButton,请记住,您可以在if语句中更改值对于您想要的那个,例如,如果您要以最少一小时的时间进行通知,则可以将其设置为3600,然后复制并粘贴…

 - (void)userSelectTime:(UIDatePicker *)sender { 

_countDownInterval = (NSTimeInterval)sender.countDownDuration;
if (_countDownInterval >= 120) {
_button.alpha = 1;
_button.userInteractionEnabled = YES;
} else {
_button.alpha = 0.3;
_button.userInteractionEnabled = NO;
}
}

现在运行该应用程序!

当您将选择器更改为超过两分钟的值时,您将看到该按钮变为启用状态,点击按钮,然后等待!

如您所见,iOS 10的LocalNotifications并不难实现,并且是一个非常有用的工具。 我要提到的最后一件事,尽管它的最佳作法是使代码保持更新,但作为开发人员,您还应该知道如何处理应用程序中向后兼容性的问题,请记住,并非每个用户都这么快地更新其手机,如果您想了解更多有关此框架的信息,请检查此链接。

您可以在此处克隆完整的项目,慢跑。

和平!