Parse.com registering for push notification after user login - parse-platform

I know that to register Parse.com push notifications I have to set it all in appdelegate file. But I am wondering if it is possible to override channels and register to multiple channels after user login in a viewcontroller class.

You should be able to by doing something like the following.
if(![currentInstallation channels]) {
[currentInstallation setChannels:#[#"WHATEVER1", #" WHATEVER2"]];
NSLog(#"Set Channel");
} else {
[currentInstall addUniqueObject:#"objectone" forKey:#"channels"];
[currentInstall addUniqueObject:#"objecttwo" forKey:#"channels"];
} [currentInstall saveInBackgroundWithBlock:(BOOL succeeded, NSError *error) {
if(!error){
NSLog(#"subscribed user to both channels");
} else {
NSLog(#"error subscribing to both channels: %#", error);
}
}];

All you have to do is run a shared instance of UIApplication anywhere in your application and then call the registration methods. Like this:
let application = UIApplication.sharedApplication()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
This will present the push notifications dialog asking if they want to allow notifications and then make the call back to the appropriate app delegate method of either didFailToRegisterForRemoteNotificationsWithError or didRegisterForRemoteNotificationsWithDeviceToken
If you are testing on a simulator and not on an actual device didFailToRegisterForRemoteNotificationsWithError will always be called.

Related

How do I use delegates within Xamarin (specifically UNUserNotificationCenterDelegate)

I need to use the iOS 10 features in UNUserNotificationCenterDelegate. How can I implement this delegate in c# / Xamarin?
When using the an UNUserNotificationCenterDelegate, make sure that you assign it in the WillFinishLaunching or the FinishedLaunching methods in your app's UIApplicationDelegate.
You must assign your delegate object to the UNUserNotificationCenter object no later before your app finishes launching.
Ref: UNUserNotificationCenterDelegate
AppDelegate.cs Example
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
// Handle the user approval or refusal of your notifications...
});
UNUserNotificationCenter.Current.Delegate = new MyUNUserNotificationCenterDelegate();
return true;
}
In that example, I am creating/assigning a delegate class named MyUNUserNotificationCenterDelegate, so you need to implement that class.
MyUNUserNotificationCenterDelegate class example:
This UNUserNotificationCenterDelegate example will capture each local notification sent and toggle between showing it on the lock screen or outputting the details to the syslog.
public class MyUNUserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
bool toggle;
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
if (toggle)
completionHandler(UNNotificationPresentationOptions.Alert);
else
{
Console.WriteLine(notification);
completionHandler(UNNotificationPresentationOptions.None);
}
toggle = !toggle;
}
}
Now you will actually need to send some notifications, this sets up a simple repeating notification:
Create/Schedule Local Notification:
// Schedule a repeating Notification...
var content = new UNMutableNotificationContent();
content.Title = new NSString("From SushiHangover");
content.Body = new NSString("StackOverflow rocks");
content.Sound = UNNotificationSound.Default;
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(timeInterval: 60, repeats: true);
var request = UNNotificationRequest.FromIdentifier(identifier: "FiveSecond", content: content, trigger: trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (NSError error) =>
{
if (error != null) Console.WriteLine(error);
});
Every 60 seconds a notification is dispatched and if you are on the lock screen you will receive an alert every 120 seconds...
Recommend reading to understand how you Xamarin.iOS/C# to interact with delegates, protocols, and events:
iOS uses Objective-C delegates to implement the delegation pattern, in which one object passes work off to another. The object doing the work is the delegate of the first object. An object tells its delegate to do work by sending it messages after certain things happen. Sending a message like this in Objective-C is functionally equivalent to calling a method in C#. A delegate implements methods in response to these calls, and so provides functionality to the application.
Ref: Xamarin.iOS and Delegates

Is it possible to automatically fetch parse objects?

Many im services automatically display messages once the user on the other end has sent a message.
Right now, the only way I can think of to do this is to use an nstimer which will run the appropriate block of code which fetches the messages and updates the table view. This is resources intensive and can waste one of the requests per second. Is there any way to automate this process and make it happen only when a new message has been sent/received?
Here's an example of using didReceiveRemoteNotification inside of your app delegate to respond to push notifications. In particular, you care about the case where you are receiving the notification while the app is active.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
if (PFUser.currentUser() == nil) {
return
}
if (application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background) {
// Received the push notification when the app was in the background
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
// Inspect userInfo for the push notification payload
if let notificationPayloadTypeKey: String = userInfo["someKey"] as? String {
// Do something
}
} else {
// Received the push notification while the app is active
if let notificationPayloadTypeKey: String = userInfo["someKey"] as? String {
// Use NSNotificationCenter to inform your view to reload
NSNotificationCenter.defaultCenter().postNotificationName("loadMessages", object: nil)
}
}
}
Then you just need to add a listener inside of your view controller. Inside of viewDidLoad add the following which will call the function loadMessages whenever a notification is received.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "loadMessages", name: "loadMessages", object: nil)
If you download the code for Parse's Anypic example project you can see how they handle remote notifications.

Storing a Boolean for access by Parse login

I want to store a Boolean which grants access to certain options when a user logs in with Parse, but when I log in and declare it to be true, the variable seems to remain false.
I tried using NSUserDefaults and storing a global variable.
This is where I log in on one view controller:
PFUser.logInWithUsernameInBackground(userName.text!, password: password.text!) {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "accessGranted")
}
This functions fine and prints "Success" if I try.
On another view controller I have things like this:
addButton.enabled = NSUserDefaults.standardUserDefaults().boolForKey("accessGranted")
You can use NSUserDefaults to store your Bool globally this way:
Set your Bool this way:
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "YourKey")
Then you can access it anywhere in your project this way:
let yourBool = NSUserDefaults.standardUserDefaults().boolForKey("YourKey")
Hope this will help.
NSUserDefaults:
Your are missing key component for it to work - you have to save the settings:
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "accessGranted")
NSUserDefaults.standardUserDefaults().synchronize()
After that, your data that you stored will be stored to disk and you can access them anytime.
One-time assign to property:
After reading through comment, in order to access property only once, you can use something like this:
var accessGranted : Bool?
if accessGranted == nil {
accessGranted = yourValue
}
or as of Swift 2.0 (more on it here):
var accessGranted : Bool?
guard let granted = accessGranted else {
accessGranted = yourValue
}
Edit 2:
To notify second VC about changes, you can use multiple mechanisms (protocols / delegates etc.), but usually for this kind of message you would use Notifications (so your whole application can listen to that).
Notifications
You can use notifications like this:
In your "login" call, notify application that your access status changed, like this:
let NOTIFICATION_ACCESS_CHANGED_KEY = "NotificationAccessChanged"
NSNotificationCenter.defaultCenter().postNotificationName(NOTIFICATION_ACCESS_CHANGED)
then, everywhere where you are interested to listen to that change, put notification listener:
NSNotificationCenter.defaultCenter().addObserverForName(NOTIFICATION_ACCESS_CHANGED, object: nil, queue: nil) { (notification) -> Void in
// This block will be called when you post notification
self.doSomething()
}
Hope it helps!

react on receipt of local notification

I'm scheduling a local notification and would like to react to the receipt of it; it works as expected when the app is in the foreground, via application:didReceiveLocalNotification:, but I can't get it to work when the app is in the background or closed - even if the app is in the background, that method is never called, neither is handleActionWithIdentifier:forLocalNotification:.
How can I achieve that an action is executed for sure at a specific time?
I would like to react to the local notification even if the user doesn't tap on the notification, so do something automatically when the local notification was received.
Generally notifications are received in two cases.
case-1: In application:didFinishLaunchingWithOptions: method, if the app is neither running nor in the background
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
// handle here
}
}
Case-2: In application:didReceiveLocalNotification: method if the app is either running or in background.
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif
{
if (app.applicationState == UIApplicationStateInactive )
{
NSLog(#"app not running");
}
else if(app.applicationState == UIApplicationStateActive )
{
NSLog(#"app running");
}
}

URL scheme - Qt and mac

I'm trying to implement a custom URL scheme for my application. I've added the necessary lines for my Info.plist. After calling the specified url (eg.: myapp://) the application launches.
If I want to handle the URL, I've found these steps:
#interface EventHandler : NSObject {
}
#end
#implementation EventHandler
- (id)init {
self = [super init];
if (self) {
NSLog(#"eventHandler::init");
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self
selector:#selector(applicationDidFinishLaunching:)
// name:NSApplicationWillFinishLaunchingNotification
name:NSApplicationDidFinishLaunchingNotification
object:nil];
}
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
[appleEventManager setEventHandler:self andSelector:#selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
}
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
NSString* url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
NSLog(#"%#", url);
}
#end
The above code is working if the application is running, but if the URL gets called and the application was terminated, the event is not caught. I think this is because this: NSApplicationDidFinishLaunchingNotification.
Changing it to NSApplicationWillFinishLaunchingNotification causes that non events caught. Maybe Qt handles it before me, but I can't find a workaround for the problem.
I was also trying to get my Qt-based application handle a custom URL scheme on the Mac and went down the same path as the original poster. It turns out that Qt4 already supports URL events on the Mac, and there's no need to write Objective-C code to receive them. This is in fact the reason that you didn't receive any URL events when you set the event handler in response to NSApplicationWillFinishLaunchingNotification: Qt registers its own handler afterward.
When a URL with your custom scheme is triggered, your Qt application will receive a FileOpenEvent. Note that it is the QApplication instance which receives the event. You can catch it by making your application subclass QApplication or by installing an event filter on the standard QApplication. I opted for this second approach.
Here's the eventFilter method of my custom event filter class, FileOpenEventFilter. It just emits the signal urlOpened when the event contains a non-empty URL. It also saves the last opened URL in case my main window isn't completely initialized when the event arrives (which happens in my app when it's not already running when the custom URL is clicked.)
bool FileOpenEventFilter::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::FileOpen)
{
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->url().isEmpty())
{
m_lastUrl = fileEvent->url().toString();
emit urlOpened(m_lastUrl);
}
else if (!fileEvent->file().isEmpty())
{
emit fileOpened(fileEvent->file());
}
return false;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
I register my handler in my application delegate's applicationWillFinishLaunching: method, and I don't miss any events. You're probably initializing your EventHandler object too late to get that notification. If you want to keep it as a separate class, that's ok, but you should create your object and register it with NSAppleEventManager within the applicationWillFinishLaunching: method of your application delegate.

Resources