How to Change UILocalNotification Text after it's shown in notification center? - ios

In one of my app, I want to show the local notification and once it's shown in notification center, I want to updated it's content.
Is it possible in Swift ?
Thanks,
HP.

Not exactly. But you can remove it and add an new one with the new text.

Here's the solution for other visitors:
https://developer.sinnerschrader-mobile.com/ios-how-to-remove-a-notification-programmatically-from-ios-notification-center/582/
Using NSKeyedArchiver, I archived my old local notification to one path and when I wanted to remove it, I deleted it from that location.
It's working fine.
Edited :
1)Cache UILocalNotificaiton using NSKeyedArchiver
NSString *archivePath = [self cachePathWithKey:key];
[NSKeyedArchiver archiveRootObject:notification toFile:archivePath];
2) Show Notification
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
3) Remove Notification Whenever you want to remove it.
NSString *archivePath = [self cachePathWithKey:key];
UILocalNotification *cachedNotification = [self notificationForKey:key];
if (cachedNotification == nil) {
return NO;
}
[[UIApplication sharedApplication] cancelLocalNotification:cachedNotification];
[[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil];
You can use this library also as I've used that one only.
https://github.com/sinnerschrader-mobile/s2m-toolbox-ios
Copy LocalNotificationHelper Folder in your project and User removeNotificationForKey and showNotification methods.
Thanks,
HP.

Related

OneSignal iOS - Can't prevent webview

I integrated OneSignal to my iOS-App (WKWebview). But its automatically opening another webview window. I just want to load the given URL into my Webview, not another one. Universal Links/Deep Linking is also integrated.
I read that I can give "additional data" to every send notification, but I do not really know how I can catch that inside my AppDelegate (or somewhere else).
I added OneSignal this way:
https://documentation.onesignal.com/docs/ios-sdk-setup
You will want to do this in the AppDelegate.m
The payload will look like this
// (Optional) - Create block that will fire when a notification is tapped on.
id notificationOpenedBlock = ^(OSNotificationOpenedResult *result) {
OSNotificationPayload* payload = result.notification.payload;
NSString* messageTitle = #"OneSignal Example";
NSString* fullMessage = [payload.body copy];
if (payload.additionalData) {
if (payload.additionalData[#"OpenURL"])
redVC.receivedUrl = [NSURL URLWithString:(NSString *)payload.additionalData[#"OpenURL"]];

iOS Toggles don't retain their state between view controllers

I have several toggles assigned to sounds. When switched on, a short clip plays for 30 seconds or so. Then when switching between viewcontrollers inside the app (eg, to the menu page) when i go back to the toggles they are all off! I would like them to retain their value after being switched on until the user decides to turn them off. This is not an issue until switching between pages inside the app.
Thanks for your help.
-(void)kickSwitchChanged:(UISwitch*)sw
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
[app setKickStep:sw.tag state:sw.isOn];
}
-(void)snareSwitchChanged:(UISwitch*)sw
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
[app setSnareStep:sw.tag state:sw.isOn];
}
What you have sounds like a good use case for NSUserDefaults.
NSUserDefaults allows you to store data that will be persisted all the way through terminating and relaunching your app. It is meant to be used for "lighter-weight" data, like if a user wants a switch on or off.
Here is an example of saving a boolean default:
let kMySwitchDefaultKey = "isMySwitchOn"
NSUserDefaults.standardUserDefaults().setBool(mySwitch.on, forKey: kMySwitchDefaultKey)
Here is an example of retrieving the same boolean default:
let wasMySwitchOn = NSUserDefaults.standardUserDefaults().boolForKey(kMySwitchDefaultKey)
Typically you would set the default when the user changes the switch value, and you would get the default somewhere like viewWillAppear and use the saved value to update the switch state to be what it previously was set to.
Source: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html
Edit
I didn't see your Obj-C tag. Here is the same setting and getting code in Obj-C.
Setting
NSString* const kMySwitchDefaultKey = #"isMySwitchOn";
[[NSUserDefaults standardUserDefaults] setBool:mySwitch.on forKey:kMySwitchDefaultKey];
Getting
BOOL wasMySwitchOn = [[NSUserDefaults standardUserDefaults] boolForKey:kMySwitchDefaultKey];

How to updated 3D Touch Quick Actions localized Subtitle?

I am adding all my 3D Touch actions in my app delegate but how can I update the subtitle of one of the actions throughout my app?
Take a look at this reference from Apple. The first code sample gives you what you need to modify an existing quick action with a new localizedTitle.
Here's the Objective-C code from the Apple example. In summary, you create a UIMutableApplicationShortcutItem with a mutable copy of the shortcut item you want to modify. Change the title and then replace the previous shortcut with the new one.
NSArray <UIApplicationShortcutItem *> *existingShortcutItems = [[UIApplication sharedApplication] shortcutItems];
UIApplicationShortcutItem *anExistingShortcutItem = [existingShortcutItems objectAtIndex: anIndex];
NSMutableArray <UIApplicationShortcutItem *> *updatedShortcutItems = [existingShortcutItems mutableCopy];
UIMutableApplicationShortcutItem *aMutableShortcutItem = [anExistingShortcutItem mutableCopy];
[aMutableShortcutItem setLocalizedTitle: #“New Title”];
[updatedShortcutItems replaceObjectAtIndex: anIndex withObject: aMutableShortcutItem];
[[UIApplication sharedApplication] setShortcutItems: updatedShortcutItems];

Best Way to Handle Local Notifications

I have the following problem:
I have 2 calendars which both need to create local notifications (which will fire 5 min before each event). In the settings the user has the ability to turn notifications on or off for either calendar. If the user was originally using the notifications for both calendars and now wants to only use notifications for one calendar, how can I delete only the notifications in one calendar?
I think I have 3 options:
Running [[UIApplication sharedApplication] cancelAllLocalNotifications]; and then add back all the ones in the other calendar (this will probably be harder than it sounds).
Storing arrays of created notifications in something like the user defaults and then looping through the arrays calling: [[UIApplication sharedApplication] cancelLocalNotification:notification];
Subclassing UILocalNotification and adding some field which will allow me to sort the notifications. Then maybe I could call [[UIApplication sharedApplication] scheduledLocalNotifications] and loop through that checking that field and deleting those which are necessary.
Is there a standard way of doing this? I think the third is probably the easiest, but I'm not sure if it would work.
UILocalNotification has a standard userInfo property that is a NSDictionary of arbitrary values as long as the keys are valid property-list types. If you subclass UILocalNotification, you must use that dictionary as the backing store for additional properties or fields you wish to persist. And to be able to use your subclass, you will need an initialization method that will copy the properties from the base class to your subclass.
#define kNoficationCalendarName NSStringFromSelector(#selector(calendarName))
#interface XXLocalNotification : UILocalNotification
#property (nonatomic, strong) NSString * calendarName;
- (instancetype)initWithLocalNotification:(UILocalNotification *)notification;
#end
#implementation XXLocalNotification
- (instancetype)initWithLocalNotification:(UILocalNotification *)notification
{
self = [super init];
if (self)
{
//Copy properties
self.alertAction = notification.alertAction;
self.alertBody = notification.alertBody;
self.alertLaunchImage = notification.alertLaunchImage;
self.applicationIconBadgeNumber = notification.applicationIconBadgeNumber;
self.fireDate = notification.fireDate;
self.hasAction = notification.hasAction;
self.repeatCalendar = notification.repeatCalendar;
self.repeatInterval = notification.repeatInterval;
self.soundName = notification.soundName;
self.timeZone = notification.timeZone;
self.userInfo = notification.userInfo;
}
return self;
}
-(void)setCalendarName:(NSString *)calendarName
{
NSMutableDictionary * userInfo = [[self userInfo] mutableCopy];
[userInfo setValue:calendarName
forKey:kNoficationCalendarName];
}
- (NSString *)calendarName
{
return [[self userInfo] valueForKey:kNoficationCalendarName];
}
#end

iCloud - renaming open documents on another device sometimes fails

The issue: I'm working on an iCloud document on device A, e.g. iPod Touch. Then I change the name of the document on device B, e.g. my Mac (via the Finder). The change goes up to the cloud and after a pause device A gets to hear about it.
And then:
some of the time all is just fine - I pick up the change of name via a changed fileURL property and can update my interface accordingly - the document continues to behave just as it should
some of the time, the document's fileURL is returned as something such as: file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95 Not surprisingly this file won't save.
Can anyone explain what is going on and how to work around it?
Background
The name change is picked up fine by by NSMetadataQuery. So, for e.g., I can rename documents that are not open and all my iCloud functionality works fine. The issue only seems to occur with open documents.
Other iCloud features are working fine, e.g. I can change content on one device, e.g. my Mac, and detect and then update my interface on another device, e.g. my iPod Touch, that has the relevant iCloud document open.
I first spotted this when I added an override for presentedItemDidMoveToURL: to my UIDocument subclass. The override reliably picks up name changes made in the cloud, e.g. renaming the document on another device. Then sometimes newURL is the final expected URL for the renamed document, i.e. something sensible from which I can extract the new name use `lastPathComponent', update my interface etc. On other occasions newURL is a document in some other directory with a last path component beginning 'purg-', e.g. purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95.
- (void) presentedItemDidMoveToURL:(NSURL *) newURL;
{
[super presentedItemDidMoveToURL: newURL];
if ([(id)[self delegate] respondsToSelector:#selector(documentNameChanged:)])
{
[[self delegate] documentNameChanged: self];
}
}
The presentedItemDidMoveToURL: method does not seem to be the root cause of the problem. For example, if I don't override that method at all, but periodically check in the viewController that is looking after the open document, then sometimes after a rename fileURL will return the new name and sometimes it will return `purg-.....'. So the issue appears to be to do with how renaming is handled.
Update
As al_lea pointed out, the issue here was related to accommodatePresentedItemDeletionWithCompletionHandler:. Expanding on al_lea's answer, I added the code below to my UIDocument subclass. This fixed the issue.
- (void) accommodatePresentedItemDeletionWithCompletionHandler: (void (^) (NSError *errorOrNil)) completionHandler
{
PresentedDocument* presentedDocument = [self retain];
[presentedDocument closeWithCompletionHandler: ^(BOOL success) {
NSError* error = nil;
if (!success)
{
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
#"Could not close document that is being deleted on another device",
NSLocalizedDescriptionKey, nil];
error = [NSError errorWithDomain: #"some_suitable_domain"
code: 101
userInfo: userInfo];
}
completionHandler(error); // run the passed in completion handler (required)
dispatch_async(dispatch_get_main_queue(), ^
{
[[NSNotificationCenter defaultCenter] postNotificationName: NOTIFY_presentedDocumentDeletedOnAnotherDevice
object: presentedDocument
userInfo: nil];
[presentedDocument tidyUpAfterDelete]; // app specific tidy up
[presentedDocument release];
});
}];
}
With this code in place, there are no spurious and confusing presentedItemDidMoveToURL: calls made and, in addition, the relevant object can listen for notifications of deletions on other devices.
This type of URL appears when a UIDocument is opened on local and get deleted from a remote device:
file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-
You need to close the document first before it get deleted - detect this in NSFilePresenter's accommodatePresentedItemDeletionWithCompletionHandler:

Resources