开发者

Custom Core Data accessors for transformable UILocalNotification

开发者 https://www.devze.com 2023-01-20 02:36 出处:网络
I开发者_StackOverflow have a transformable attribute on one of my entities, called reminder. It\'s a UILocalNotification.

I开发者_StackOverflow have a transformable attribute on one of my entities, called reminder. It's a UILocalNotification.

Now, since I want to schedule it when it's added, and cancel it when removed, I would like to override the accessors to handle the scheduling and cancelling in there.

How would that look?

Thanks!


Are you actually persisting the UILocalNotification or are you using it as a transient property?

I wouldn't store it, rather UILocalNotification as a userInfo as a property. You can at a key/value pair to that dictionary with information about the owning entity. For instance:

You create a value for the key notificationID in the userInfo dictionary and set a attribute notificationID on your Core Data entity to the same value. That way, you just have to store an int or NSString in your store (which is preferable to transformable).

When you want to fetch your UILocalNotification again you can make an accessor on your Entity Class, something like:

- (void)createNotification
{
    static NSUInteger kDeadlineWarningPeriod = 3600;
    UILocalNotification *notification = [[UILocalNotification alloc] init];

    …

    self.notificationID = @"some generated ID";

    [notification.userInfo setValue:self.notificationID forKey:@"notificationID"];

    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    [notification release];
}

- (void)cancelNotification
{
    // We search for the notification.
    // The entity's ID will be stored in the notification's user info.

    [[[UIApplication sharedApplication] scheduledLocalNotifications] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    UILocalNotification *notification = (UILocalNotification *)obj;
    NSDictionary *userInfo = notification.userInfo;

    NSString *notificationID = [userInfo valueForKey:@"notificationID"];

    if ([notificationID isEqualToString:self.notificationID])
    {
        [[UIApplication sharedApplication] cancelLocalNotification:notification];
        *stop = YES;
                    self.notificationID = nil;
    }
     }];
}

Of course you can make an accessor for your notification in much the same way if you actually need access to the notification object.

Hope it helps.

UPDATE

So since you have a property you call reminder on you Entity (I'm guessing that it is a BOOL) it will look something like this:

// .h

@property (nonatomic, assign) BOOL reminder;

// .m

- (void)setReminder:(BOOL)reminder {

   [self willAccessValueForKey@"reminder"];
   BOOL hasReminder = [[self primitiveValueForKey:@"reminder"] booleanValue];
   [self didAccessValueForKey:@"reminder"];

   if (hasReminder && !reminder) {

        [self cancelNotification];
   }
   else if (!hasReminder && reminder) {

        [self createNotification];
   }

   if (reminder != hasReminder)
   {
        [self willChangeValueForKey:@"reminder"];
        [self setPrimitiveValue:[NSNumber numberWithBool:reminder] forKey@"reminder"];
        [self didChangeValueForKey:@"reminder"];
   }
}

In fact you don't really have to store the "reminder" attribute at all, you can just check if the notificationID attribute is nil or not. That was the idea from my suggestion before.

I haven't checked the code above but I do something similar in two of my projects.

Remember you can get into trouble if you create more than 64 local notifications, since you are only allowed to make that many per app. So you might want to track how many you have before creating any new ones.


If you have only one notification for each object, then you could avoid having to store a notificationID and just use the objectId of the NSManagedObject in the Persistent store.

You can serialize and deserialize the objectId with the following lines of code:

[[self.objectID URIRepresentation] absoluteString] 

and

[[self persistentStoreCoordinator] managedObjectIDForURIRepresentation:[NSURL URLWithString:[localNotif.userInfo objectForKey: kYourReminderNotificationKey]

here is the code edited:

- (void)createNotification
{        

    Class cls = NSClassFromString(@"UILocalNotification");
    if (cls != nil) {

        UILocalNotification *notif = [[cls alloc] init];
        notif.fireDate = self.dateDue;
        notif.timeZone = [NSTimeZone defaultTimeZone];


       notif.alertBody = @"Alert body";        

        notif.alertAction = @"Show me";
        notif.soundName = UILocalNotificationDefaultSoundName;


        NSDictionary *userDict = [NSDictionary dictionaryWithObject:[[self.objectID URIRepresentation] absoluteString] forKey:kRemindMeNotificationDataKey];


        notif.userInfo = userDict;

        [[UIApplication sharedApplication] scheduleLocalNotification:notif];

    }


}

- (void)cancelNotification
{

    [[[UIApplication sharedApplication] scheduledLocalNotifications] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        UILocalNotification *notification = (UILocalNotification *)obj;
        NSDictionary *userInfo = notification.userInfo;

        NSString *notificationID = [userInfo valueForKey:kRemindMeNotificationDataKey];

        if ([notificationID isEqualToString:[[self.objectID URIRepresentation] absoluteString]])
        {
            [[UIApplication sharedApplication] cancelLocalNotification:notification];
            *stop = YES;
        }
    }];
}
0

精彩评论

暂无评论...
验证码 换一张
取 消