ローカル通知に基づいて iPhone アラーム アプリを開発しています。
アラームを削除すると、関連するローカル通知がキャンセルされます。しかし、ローカル通知の配列からどのオブジェクトをキャンセルするかを正確に判断するにはどうすればよいでしょうか?
メソッドは認識して[[UIApplication sharedApplication] cancelLocalNotification:notification]
いますが、この「通知」を取得してキャンセルするにはどうすればよいですか?
ローカル通知に基づいて iPhone アラーム アプリを開発しています。
アラームを削除すると、関連するローカル通知がキャンセルされます。しかし、ローカル通知の配列からどのオブジェクトをキャンセルするかを正確に判断するにはどうすればよいでしょうか?
メソッドは認識して[[UIApplication sharedApplication] cancelLocalNotification:notification]
いますが、この「通知」を取得してキャンセルするにはどうすればよいですか?
キーの一意の値をローカル通知のユーザー情報に保存できます。すべてのローカル通知を取得し、配列をループして特定の通知を削除します。
次のようなコード、
OBJ-C:
UIApplication *app = [UIApplication sharedApplication];
NSArray *eventArray = [app scheduledLocalNotifications];
for (int i=0; i<[eventArray count]; i++)
{
UILocalNotification* oneEvent = [eventArray objectAtIndex:i];
NSDictionary *userInfoCurrent = oneEvent.userInfo;
NSString *uid=[NSString stringWithFormat:@"%@",[userInfoCurrent valueForKey:@"uid"]];
if ([uid isEqualToString:uidtodelete])
{
//Cancelling local notification
[app cancelLocalNotification:oneEvent];
break;
}
}
迅速:
var app:UIApplication = UIApplication.sharedApplication()
for oneEvent in app.scheduledLocalNotifications {
var notification = oneEvent as UILocalNotification
let userInfoCurrent = notification.userInfo! as [String:AnyObject]
let uid = userInfoCurrent["uid"]! as String
if uid == uidtodelete {
//Cancelling local notification
app.cancelLocalNotification(notification)
break;
}
}
ユーザー通知:
UserNotification (iOS 10 以降)を使用する場合は、次の手順に従ってください。
UserNotification コンテンツを作成するときに、一意の識別子を追加します
removePendingNotificationRequests(withIdentifiers:)を使用して特定の保留中の通知を削除します
removeDeliveredNotifications(withIdentifiers:)を使用して特定の配信済み通知を削除する
詳細については、UNUserNotificationCenter
その他のオプション:
まず第一に, ローカル通知を作成するとき, 将来の使用のためにそれをユーザーデフォルトに保存できます. ローカル通知オブジェクトはユーザーデフォルトに直接保存できません. このオブジェクトはまず NSData オブジェクトに変換する必要がありますNSData
. User defaults
. 以下はそのためのコードです。
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:localNotif];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:@"%d",indexPath.row]];
ローカル通知を保存してスケジュールした後、将来、以前に作成した通知をキャンセルする必要がある場合があるため、ユーザーのデフォルトから取得できます。
NSData *data= [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"%d",UniqueKey]];
UILocalNotification *localNotif = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"Remove localnotification are %@", localNotif);
[[UIApplication sharedApplication] cancelLocalNotification:localNotif];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:@"%d",UniqueKey]];
お役に立てれば
これが私がすることです。
通知を作成するときは、次のようにします。
// Create the notification
UILocalNotification *notification = [[UILocalNotification alloc] init] ;
notification.fireDate = alertDate;
notification.timeZone = [NSTimeZone localTimeZone] ;
notification.alertAction = NSLocalizedString(@"Start", @"Start");
notification.alertBody = **notificationTitle**;
notification.repeatInterval= NSMinuteCalendarUnit;
notification.soundName=UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notification] ;
削除しようとするときは、次のようにします。
NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ;
for (UILocalNotification *localNotification in arrayOfLocalNotifications) {
if ([localNotification.alertBody isEqualToString:savedTitle]) {
NSLog(@"the notification this is canceld is %@", localNotification.alertBody);
[[UIApplication sharedApplication] cancelLocalNotification:localNotification] ; // delete the notification from the system
}
}
このソリューションは、複数の通知に対して機能するはずであり、配列、辞書、またはユーザーのデフォルトを管理していません。システム通知データベースに既に保存したデータを使用するだけです。
これが将来のデザイナーや開発者に役立つことを願っています。
みんなハッピーコーディング!:D
iMOBDEV's solution works perfectly to remove a specific notification (e.g. after deleting the alarm) but it's specially useful when you need to selectively remove any notification that has already fired and is still on the notification center.
A possible scenario would be: the notification for an alarm fires, but the user opens the app without tapping on that notification and schedules that alarm again. If you want to make sure only one notification can be on the notification center for a given item/alarm, it's a good approach. It also allows you not having to clear all notifications every time the app is opened, shall that fit the app better.
NSKeyedArchiver
to store it as Data
in UserDefaults
. You can create a key equal to what you're saving in the notification's userInfo dictionary. If it's associated with a Core Data object, you could use its unique objectID property. NSKeyedUnarchiver
. Now you're able to delete it using the cancelLocalNotification method.UserDefaults
accordingly.Here's a Swift 3.1 version of that solution (for targets below iOS 10):
Store
// localNotification is the UILocalNotification you've just set up
UIApplication.shared.scheduleLocalNotification(localNotification)
let notificationData = NSKeyedArchiver.archivedData(withRootObject: localNotification)
UserDefaults.standard.set(notificationData, forKey: "someKeyChosenByYou")
Retrieve and delete
let userDefaults = UserDefaults.standard
if let existingNotificationData = userDefaults.object(forKey: "someKeyChosenByYou") as? Data,
let existingNotification = NSKeyedUnarchiver.unarchiveObject(with: existingNotificationData) as? UILocalNotification {
// Cancel notification if scheduled, delete it from notification center if already delivered
UIApplication.shared.cancelLocalNotification(existingNotification)
// Clean up
userDefaults.removeObject(forKey: "someKeyChosenByYou")
}
必要に応じて Swift バージョン:
func cancelLocalNotification(UNIQUE_ID: String){
var notifyCancel = UILocalNotification()
var notifyArray = UIApplication.sharedApplication().scheduledLocalNotifications
for notifyCancel in notifyArray as! [UILocalNotification]{
let info: [String: String] = notifyCancel.userInfo as! [String: String]
if info[uniqueId] == uniqueId{
UIApplication.sharedApplication().cancelLocalNotification(notifyCancel)
}else{
println("No Local Notification Found!")
}
}
}
Swift 2.0 でこの関数を使用します。
static func DeleteNotificationByUUID(uidToDelete: String) -> Bool {
let app:UIApplication = UIApplication.sharedApplication()
// loop on all the current schedualed notifications
for schedualedNotif in app.scheduledLocalNotifications! {
let notification = schedualedNotif as UILocalNotification
let urrentUi = notification.userInfo! as! [String:AnyObject]
let currentUid = urrentUi["uid"]! as! String
if currentUid == uidToDelete {
app.cancelLocalNotification(notification)
return true
}
}
return false
}
@KingofBlissの回答に触発されました
渡すcancelLocalNotification:
UILocalNotification オブジェクトは、一致するプロパティを持つ既存の UILocalNotification オブジェクトと一致します。
そう:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"foo";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
後でキャンセルできるローカル通知を表示します。
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"foo";
[[UIApplication sharedApplication] cancelLocalNotification:notification];
KingofBliss の回答を少し拡張し、これをもう少し Swift2 風に書き、不要なコードをいくつか削除し、いくつかのクラッシュ ガードを追加しました。
まず、通知を作成するときに、通知の uid (または実際には任意のカスタム プロパティ) を設定する必要がありますuserInfo
。
notification.userInfo = ["uid": uniqueid]
次に、それを削除するときに、次のことができます。
guard
let app: UIApplication = UIApplication.sharedApplication(),
let notifications = app.scheduledLocalNotifications else { return }
for notification in notifications {
if
let userInfo = notification.userInfo,
let uid: String = userInfo["uid"] as? String where uid == uidtodelete {
app.cancelLocalNotification(notification)
print("Deleted local notification for '\(uidtodelete)'")
}
}
繰り返しリマインダーの場合 (たとえば、日曜日、土曜日、水曜日の午後 4 時にアラームを鳴らしたい場合、3 つのアラームを作成し、repeatInterval を NSWeekCalendarUnit に設定する必要があります)。
一度だけリマインダーを作成する場合:
UILocalNotification *aNotification = [[UILocalNotification alloc] init];
aNotification.timeZone = [NSTimeZone defaultTimeZone];
aNotification.alertBody = _reminderTitle.text;
aNotification.alertAction = @"Show me!";
aNotification.soundName = UILocalNotificationDefaultSoundName;
aNotification.applicationIconBadgeNumber += 1;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit| NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: _reminderDate];
[componentsForFireDate setHour: [componentsForFireDate hour]] ; //for fixing 8PM hour
[componentsForFireDate setMinute:[componentsForFireDate minute]];
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
aNotification.fireDate = fireDateOfNotification;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey];
aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
繰り返しリマインダーを作成する場合:
for (int i = 0 ; i <reminderDaysArr.count; i++)
{
UILocalNotification *aNotification = [[UILocalNotification alloc] init];
aNotification.timeZone = [NSTimeZone defaultTimeZone];
aNotification.alertBody = _reminderTitle.text;
aNotification.alertAction = @"Show me!";
aNotification.soundName = UILocalNotificationDefaultSoundName;
aNotification.applicationIconBadgeNumber += 1;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit| NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: _reminderDate];
[componentsForFireDate setWeekday: [[reminderDaysArr objectAtIndex:i]integerValue]];
[componentsForFireDate setHour: [componentsForFireDate hour]] ; // Setup Your Own Time.
[componentsForFireDate setMinute:[componentsForFireDate minute]];
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
aNotification.fireDate = fireDateOfNotification;
aNotification.repeatInterval = NSWeekCalendarUnit;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey];
aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
}
}
フィルタリングするには、配列を表示します。
-(void)filterNotficationsArray:(NSMutableArray*) notificationArray{
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication] scheduledLocalNotifications]];
NSMutableArray *uniqueArray = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
for (int i = 0 ; i<_dataArray.count; i++) {
UILocalNotification *localNotification = [_dataArray objectAtIndex:i];
NSString * infoDict = [localNotification.userInfo objectForKey:@"kRemindMeNotificationDataKey"];
if (![names containsObject:infoDict]) {
[uniqueArray addObject:localNotification];
[names addObject:infoDict];
}
}
_dataArray = uniqueArray;
}
一度だけまたは繰り返した場合でもリマインダーを削除するには:
- (void) removereminder:(UILocalNotification*)notification
{
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]];
NSString * idToDelete = [notification.userInfo objectForKey:@"kRemindMeNotificationDataKey"];
for (int i = 0 ; i<_dataArray.count; i++)
{
UILocalNotification *currentLocalNotification = [_dataArray objectAtIndex:i];
NSString * notificationId = [currentLocalNotification.userInfo objectForKey:@"kRemindMeNotificationDataKey"];
if ([notificationId isEqualToString:idToDelete])
[[UIApplication sharedApplication]cancelLocalNotification:currentLocalNotification];
}
_dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]];
[self filterNotficationsArray:_dataArray];
[_remindersTV reloadData];
}