I have an application in Xcode 4.5 which integrates Facebook. I am using ARC. The application uses
native dialogs and therefore deprecated headers (ie Facebook.h). Apparently doing so leads to the following
error when closing/cleaning the active session:
"An instance 0xa089350 of class
FBSessionManualTokenCachingStrategy was deallocated while key value observers were still registered
with it. Observation info was leaked, and may even become mistakenly attached to some other object."
Upon researching this error, I assume that the issue is that when I init an instance of self.Facebook in the app delegate, Facebook
adds two observers rather than one, and then only one is cleaned up during logout. I have made numerous attempts to remove both instances, including every solution on this
page regarding this very error: facebook ios sdk log : strange message
None of these solutions have worked for me, including one solution I saw which involved deallocation which I cannot use as I am using ARC. Here is my code for opening and closing a session for reference:
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if (!error) {
// We have a valid session
// Initiate a Facebook instance
self.facebook = [[Facebook alloc]
initWithAppId:FBSession.activeSession.appID
andDelegate:nil];
// Store the Facebook session information
self.facebook.accessToken = FBSession.activeSession.accessToken;
self.facebook.expirationDate = FBSession.activeSession.expirationDate;
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
// Clear out the Facebook instance
self.facebook = nil;
break;
default:
break;
}
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
if (error) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
/*
* Opens a Facebook session and optionally shows the login UX.
*/
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI //do I need this method?
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_about_me",
#"read_friendlists",
#"read_stream",
#"friends_likes",
#"user_likes",
#"friends_photos",
#"user_photos",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session state:state
error:error]; }];
}
/*
* If we have a valid session at the time of openURL call, we handle
* Facebook transitions by passing the url argument to handleOpenURL
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBSession.activeSession handleOpenURL:url];
}
- (void) closeSession {
[FBSession.activeSession closeAndClearTokenInformation];
}
If anyone can offer any guidance as to how to solve this I would greatly appreciate it.
Related
I had a working share routine and now it is broken. Hadn't checked it, or modified it, for some time and now find that it is inoperable. When I call
[sharingService performWithItems:[NSArray arrayWithObject:itemProvider]];
I get a share sheet displayed. It shows the current members of the share. The form is inoperable and will not accept any input or taps. I cannot add, remove or stop sharing altogether. When I close the form, my app is hung up and will not respond or take focus. I have to kill the app and reopen to get it working again.
This used to work fine, within the last few months. I hadn't changed anything so I am very surprised by new problem.
I am adding my code for creating share here:
NSString *shareOption = [[NSUserDefaults standardUserDefaults] objectForKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
if ([shareOption isEqualToString:TTICloudKitShareOwnerService]) {
CDEZipCloudFileSystem *zipFile = (CDEZipCloudFileSystem *)_cloudFileSystem;
CDECloudKitFileSystem *fileSystem = (CDECloudKitFileSystem *)zipFile.cloudFileSystem;
NSItemProvider *itemProvider = [[NSItemProvider alloc] init];
[itemProvider registerCloudKitShare:fileSystem.share container:fileSystem.container];
NSSharingService *sharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameCloudSharing];
sharingService.subject = #"Share Workforce Data";
sharingService.delegate = self;
if ([sharingService canPerformWithItems:[NSArray arrayWithObject:itemProvider]]) {
[sharingService performWithItems:[NSArray arrayWithObject:itemProvider]];
// This is the point at which the Apple UI is presented but inoperable.
// No changes can be made to the share.
// The only way to dismiss the dialog is to quit or press escape.
// Upon dismissal the app is either crashed or hung up.
// Quitting the app and restart is only option to use the app again.
// If not run from Xcode, requires force quit.
}
} else {
NSLog(#"Is Shared Ensemble");
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:#"Stop Share"];
[alert addButtonWithTitle:#"Cancel"];
[alert setMessageText:#"Shared Data Options"];
[alert setInformativeText:#"You are participating in a shared file. Stop sharing will remove your participation and reset your data. You will no longer participate or have access to the shared information."];
[alert setAlertStyle:NSAlertStyleWarning];
if ([alert runModal] == NSAlertFirstButtonReturn) {
[alert setInformativeText:#"Are you sure? You will no longer have access to shared data. You will need the owner of the share to resend an invitation to join the share."];
if ([alert runModal] == NSAlertFirstButtonReturn) {
// This actually does not remove user from sharing as intended.
// I am sure that is my own implementation incomplete though.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setNilValueForKey:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT];
[defaults setObject:TTICloudKitShareOwnerService forKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
[defaults synchronize];
[self disconnectFromSyncServiceWithCompletion:^{
// TODO: Need to wipe the existing Core Data info here. Leave them with no access to shared data.
// Also need to remove self from the share?
[self reset];
[self setupEnsemble];
}];
}
}
}
Creating share and sending worked flawlessly and I'd been developing app and testing live. Currently my test is shared with two other users and still works. In fact I can't seem to find a way to stop sharing with those users or in any way alter the current share at all.
This is the NSCloudSharingServiceDelegate code:
-(NSCloudKitSharingServiceOptions)optionsForSharingService:(NSSharingService *)cloudKitSharingService shareProvider:(NSItemProvider *)provider
{
return NSCloudKitSharingServiceAllowPrivate | NSCloudKitSharingServiceAllowReadWrite;
}
-(void)sharingService:(NSSharingService *)sharingService willShareItems:(NSArray *)items
{
DLog(#"Will Share Called with items:%#",items);
}
-(void)sharingService:(NSSharingService *)sharingService didShareItems:(NSArray *)items
{
DLog(#"Did share called");
}
-(void)sharingService:(NSSharingService *)sharingService didFailToShareItems:(NSArray *)items error:(NSError *)error
{
DLog(#"Sharing service failed to share items, %#-", error);
if (error.code == NSUserCancelledError) return;
DLog(#"Failed to share, error- %#", error.userInfo);
[self disconnectFromSyncServiceWithCompletion:^{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT forKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
[defaults setNilValueForKey:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT];
[defaults synchronize];
}];
}
It is apparent that I am one of the very few who find this to be important as I have scoured the webs and found almost nobody discussing it. Apple documentation is just about nil.
This is a screenshot of the Apple UI which is not working:
I am posting this as an answer, is more like a work around that I have managed to get working. Still no answer as to why the Apple UI does not respond.
See code for inviting participants without the Apple UI.
-(void)addParticipantWithEmail:(NSString *)email toShare:(CKShare *)share inContainer:(CKContainer *)container
{
[container discoverUserIdentityWithEmailAddress:(email) completionHandler:^(CKUserIdentity * _Nullable userInfo, NSError * _Nullable error) {
if (!userInfo || error) {
NSLog(#"Participant was not found for email %#", email);
if (error) {
NSLog(#"Error: %#", error.userInfo);
} else {
NSLog(#"No error was provided");
}
// abort
return;
}
CKFetchShareMetadataOperation *fetchMetaDataOperation = [[CKFetchShareMetadataOperation alloc] initWithShareURLs:[NSArray arrayWithObject:share.URL]];
fetchMetaDataOperation.shouldFetchRootRecord = YES;
[fetchMetaDataOperation setPerShareMetadataBlock:^(NSURL * _Nonnull shareURL, CKShareMetadata * _Nullable shareMetadata, NSError * _Nullable error) {
CKRecord *root = shareMetadata.rootRecord;
if (!root) {
NSLog(#"There was an error retrieving the root record- %#", error);
} else {
NSLog(#"Root is %#", root);
NSLog(#"/n");
}
CKUserIdentityLookupInfo *info = userInfo.lookupInfo;
CKFetchShareParticipantsOperation *fetchOperation = [[CKFetchShareParticipantsOperation alloc] initWithUserIdentityLookupInfos:[NSArray arrayWithObject:info]];
[fetchOperation setShareParticipantFetchedBlock:^(CKShareParticipant * _Nonnull participant) {
participant.permission = CKShareParticipantPermissionReadWrite;
[share addParticipant:participant];
CKModifyRecordsOperation *modifyOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:[NSArray arrayWithObjects:root, share, nil] recordIDsToDelete:nil];
modifyOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged;
[modifyOperation setPerRecordCompletionBlock:^(CKRecord * _Nonnull record, NSError * _Nullable error) {
if (error) {
DLog(#"Error modifying record %#. UserInfo: %#", record, error.userInfo);
} else {
DLog(#"No Error Reported in Modify Operation");
}
}];
[container.privateCloudDatabase addOperation:modifyOperation];
}];
[fetchOperation setFetchShareParticipantsCompletionBlock:^(NSError * _Nullable operationError) {
if (operationError) {
NSLog(#"There was en error in the fetch operation- %#", operationError.userInfo);
// Error may be a network issue, should implement a retry and possibly a limit to how many times to run it
}
}];
[container addOperation:fetchOperation];
}];
[container addOperation:fetchMetaDataOperation];
}];
}
It seems now, if I pass an email address to this function they are successfully invited to share, provided the user is in my contacts and has allowed discoverability.
I send the user the link to the share manually via iMessage at this point. Copied the URL from the console. My intent is to provide my own forms to handle that now.
On receiving link, I use Ensembles method:
CDECloudKitFileSystem acceptInvitationToShareWithMetadata:metadata completion:^(NSError *error)
This code didn't seem to work, accepting invites was failing initially. Without having changed anything, the accepting shares started to work. I am not sure why the initial fails.
I have two Cocoa Applications, one is going to be the sender and another the receiver in this XPC relationship.
In the applicationDidFinishLaunching in the sender, I first open the second receiver application
NSError* error = nil;
NSURL* url = [[NSBundle mainBundle] bundleURL];
url = [url URLByAppendingPathComponent:#"Contents" isDirectory:YES];
url = [url URLByAppendingPathComponent:#"MacOS" isDirectory:YES];
url = [url URLByAppendingPathComponent:#"TestXPCHelper.app" isDirectory:YES];
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:url
options:NSWorkspaceLaunchWithoutActivation
configuration:[NSDictionary dictionary]
error:&error];
if ( error )
{
NSLog(#"launchApplicationAtURL:%# error = %#", url, error);
[[NSAlert alertWithError:error] runModal];
}
Then I create my NSXPCConnection
assert([NSThread isMainThread]);
if (self.testConnection == nil) {
self.testConnection = [[NSXPCConnection alloc] initWithMachServiceName:NEVER_TRANSLATE(#"com.TechSmith.TestXPCHelper") options:NSXPCConnectionPrivileged];
self.testConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:#protocol(TestXPCProtocol)];
self.testConnection.interruptionHandler = ^{
NSLog(#"Connection Terminated");
};
self.testConnection.invalidationHandler = ^{
self.testConnection.invalidationHandler = nil;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.testConnection = nil;
}];
};
[self.testConnection resume];
}
Then I try to send a message over the connection (the connection is already invalidated by here)
id<TestXPCProtocol> testRemoteObject= [self.testConnection remoteObjectProxy];
[testRemoteObject testXPCMethod2];
[[self.testConnection remoteObjectProxyWithErrorHandler:^(NSError * proxyError){
NSLog(#"%#", proxyError);
}] testXPCMethod:^(NSString* reply) {
NSLog(#"%#", reply);
}];
And here is the app delegate for my receiver application:
#interface AppDelegate () <NSXPCListenerDelegate, TestXPCProtocol>
#property (weak) IBOutlet NSWindow *window;
#property NSXPCListener *xpcListener;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSLog(#"TESTING123");
self.xpcListener = [[NSXPCListener alloc] initWithMachServiceName:#"com.TechSmith.TestXPCHelper"];
self.xpcListener.delegate = self;
[self.xpcListener resume];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification {
NSLog(#"ACTIVE234");
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (void)run
{
NSLog(#"RUNNING");
// Tell the XPC listener to start processing requests.
[self.xpcListener resume];
// Run the run loop forever.
[[NSRunLoop currentRunLoop] run];
}
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
{
NSLog(#"LISTENING");
assert(listener == self.xpcListener);
#pragma unused(listener)
assert(newConnection != nil);
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:#protocol(TestXPCProtocol)];
newConnection.exportedObject = self;
[newConnection resume];
return YES;
}
- (void)testXPCMethod:(void(^)(NSString * version))reply
{
NSLog(#"HEY");
reply(#"REPLY HERE");
}
- (void)testXPCMethod2
{
NSLog(#"TWO!");
}
Here is the proxyError when I try to send a message over the connection:
Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service
named com.TechSmith.TestXPCHelper was invalidated." UserInfo={NSDebugDescription=The
connection to service named com.TechSmith.TestXPCHelper was invalidated.}
So I think I am doing something wrong with my instantiation of the NSXPCConnection. I can't find a good example of two applications speaking to eachother-- it's always one application and a service. Is that what my problem is? I need a service inbetween the applications talking?
Is there any way to get more information on why this connection is being invalidated? That would also help a lot
So pretty straight forward problem here,
Turns out initWithMachServiceName is explicitly looking for a mach service. I was using an identifier of another application process.
If I actually use an identifier of a valid mach service, there is no issue
Note that there are two other ways to create an NSXPCConnection,
with an NSXPCEndpoint or with a XPCService identifier
I'm working with TWrequest to display my twitter lists in a tableview. The following code works. The problem is it is very slow to update the table. I am NSlogging the request response (which happens very quickly), I am also looping through each list and adding the list 'name' to an array (which again, happens very quickly <1s). But for some inexplicable reason, the table takes roughly a further 4 seconds or so to update.
Why is this taking so long for the table to reload? The problem is not parsing the response (because I can see with nslog this happens pretty quick), it's taking a long time to display in the table? Help very much appreciated!
-(IBAction)getLists{
// First, we need to obtain the account instance for the user's Twitter account
ACAccountStore *store = [[ACAccountStore alloc] init];
ACAccountType *twitterAccountType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request permission from the user to access the available Twitter accounts
[store requestAccessToAccountsWithType:twitterAccountType withCompletionHandler:^(BOOL granted, NSError *error) {
if (!granted) {
// The user rejected your request
NSLog(#"User rejected access to the account.");
}
else {
// Grab the available accounts
twitterAccounts = [store accountsWithAccountType:twitterAccountType];
if ([twitterAccounts count] > 0) {
// Use the first account for simplicity
ACAccount *account = [twitterAccounts objectAtIndex:0];
// Now make an authenticated request to our endpoint
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
//[params setObject:#"1" forKey:#"include_entities"];
// The endpoint that we wish to call
NSURL *url = [NSURL URLWithString:#"http://api.twitter.com/1.1/lists/list.json"];
// Build the request with our parameter
TWRequest *request = [[TWRequest alloc] initWithURL:url parameters:params requestMethod:TWRequestMethodGET];
// Attach the account object to this request
[request setAccount:account];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (!responseData) {
// inspect the contents of error
NSLog(#"error = %#", error);
}
else {
NSError *jsonError;
NSArray *timeline = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&jsonError];
if (timeline) {
// at this point, we have an object that we can parse
NSLog(#"timeline = %#", timeline);
for (NSDictionary *element in timeline) {
NSString *listName = [element valueForKey:#"name"];
[listsArray addObject:listName];
}
[listsTable reloadData];
}
else {
// inspect the contents of jsonError
NSLog(#"jsonerror = %#", jsonError);
}
}
}];
}
}
}];
}
Sorry, just came across this post. If you haven't found a solution yet, hopefully this will help.
I believe that performRequestWithHandler can be called on any thread, so UI changes should be dispatched to the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
//update UI here
});
Or in the case of reloading table data you can use:
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
I have quite an understanding issue with displaying local notifications.
As far as I was reading in other threads, one has first create and schedule the local notification with the application.
For displaying that notification, one has to use the delegates didFinishLaunchingWithOptions: (if app is in background operation) and didReceiveLocalNotification: (if app is in foreground).
Now even though I did NOT change the didFinishLaunchingWithOptions: method, the notification is already getting viewed when my app is in the background.
It wouldn't be that big of a problem if the didFinishLaunchingWithOptions: would at least be used when I specify it at all. But it doesn't.
So my problem is, that even though I haven't used the didFinishLaunchingWithOptions: method, the notification is getting displayed. When the user clicks on the notification, the app gets to foreground and the didReceiveLocalNotification: method is triggered and the notification is displayed again.
What I originally wanted to do is to cancelAllLocalNotifications on execution of didFinishLaunchingWithOptions:, but since it is not getting executed, I'm kinda stuck here.
Ok, there might be a workaround with applicationWillEnterForeground: but honestly, I'd like to understand, why the notification is getting displayed even without having specified that in didFinishLaunchingWithOptions:.
All of your help is really appreaciated!! Thanks!!
//
// myNotificationsClass.m
//
#import "myNotificationsClass.h"
#implementation myNotificationsClass
//Sets up a Local Notification with Message, TimeFromNow, BadgeNumber and UserInfo
//no Class Instance for calling this method needed!!
+ (void)setupLocalNotificationsWithMessage: (NSString *) message andTimeFromNow: (NSTimeInterval) seconds andAlertAction: (NSString *) alertAction andBadgeNumber: (NSInteger) badgeNumber andUserInfo: (NSDictionary *) infoDict {
//[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
// create date/time information
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:seconds];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
//setup Appearence and Message
localNotification.alertBody = message; //#"Time to get up!";
localNotification.alertAction = alertAction;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = badgeNumber;
localNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
#end
//overwrites the viewWillAppear: Method from the primary Class to display a Test Notification
#implementation UIViewController (localNotification)
- (void)viewWillAppear:(BOOL)animated {
[myNotificationsClass setupLocalNotificationsWithMessage:#"First Test after 2 Seconds" andTimeFromNow:2 andAlertAction:#"GoTo iSnah" andBadgeNumber:7 andUserInfo:nil];
}
#end
//receive Local Notifications even if the App is in Foreground
//overwrites the primery method
#implementation UIResponder (localNotificationForeground)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleName"]
message:notification.alertBody
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
//reset Badge
application.applicationIconBadgeNumber = 0;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Because I don't want the Notification to be displayed twice
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleName"]
message:notification.alertBody
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
//reset Badge
application.applicationIconBadgeNumber = 0;
}
return YES;
}
#end
You are very close. If the app is running in the background, the user responding to the notification will not cause the app to "launch". "Launch" means the app is not running at all (foreground or background). So only put code in there that you want to execute when the app launches or starts as a result of the user responding to your local notification.
So what you need for your didReceiveLocalNotification method is something to check the application state to see if it was in the foreground or in the background when the user responded to the local notification.
You might do something like the following to differentiate your logic between foreground and background:
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification
if ( application.applicationState == UIApplicationStateActive ){
NSLog(#"Was already in the foreground");
}
else{
NSLog(#"Was in the background");
}
}
Minor point, however. Documentation states that the didReceiveLocalNotification method is invoked after application:didFinishLaunchingWithOptions: (if that method is implemented). So if you have both methods implemented you'll need to make sure the combination of the 2 work correctly in a "launch" situation.
Im trying to integrate Push Notifications in my iOS App. This is a Phonegap/Cordova Project. Everything is working well, without the APNS and Urban Airship.
What I have done till now? I got it to work, that I could send a Push Message from UA to my phone, but that was done with sample code from different forums and not the UA docs. So I startet to do it like in the docs of UA is showed. With that Im very confused and tried a lot.
So i did following:Took the Push Sample from UA and copied the code to AppDelegate.m what looks now like this:
// Create Airship singleton that's used to talk to Urban Airhship servers.
// Please populate AirshipConfig.plist with your info from http://go.urbanairship.com
[UAirship takeOff:takeOffOptions];
[[UAPush shared] resetBadge];//zero badge on startup
[[UAPush shared] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)];
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
UALOG(#"Application did become active.");
[[UAPush shared] resetBadge]; //zero badge when resuming from background (iOS 4+)
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
UALOG(#"APN device token: %#", deviceToken);
// Updates the device token and registers the token with UA
[[UAPush shared] registerDeviceToken:deviceToken];
/*
* Some example cases where user notification may be warranted
*
* This code will alert users who try to enable notifications
* from the settings screen, but cannot do so because
* notications are disabled in some capacity through the settings
* app.
*
*/
/*
//Do something when notifications are disabled altogther
if ([application enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone) {
UALOG(#"iOS Registered a device token, but nothing is enabled!");
//only alert if this is the first registration, or if push has just been
//re-enabled
if ([UAirship shared].deviceToken != nil) { //already been set this session
NSString* okStr = #"OK";
NSString* errorMessage =
#"Unable to turn on notifications. Use the \"Settings\" app to enable notifications.";
NSString *errorTitle = #"Error";
UIAlertView *someError = [[UIAlertView alloc] initWithTitle:errorTitle
message:errorMessage
delegate:nil
cancelButtonTitle:okStr
otherButtonTitles:nil];
[someError show];
[someError release];
}
//Do something when some notification types are disabled
} else if ([application enabledRemoteNotificationTypes] != [UAPush shared].notificationTypes) {
UALOG(#"Failed to register a device token with the requested services. Your notifications may be turned off.");
//only alert if this is the first registration, or if push has just been
//re-enabled
if ([UAirship shared].deviceToken != nil) { //already been set this session
UIRemoteNotificationType disabledTypes = [application enabledRemoteNotificationTypes] ^ [UAPush shared].notificationTypes;
NSString* okStr = #"OK";
NSString* errorMessage = [NSString stringWithFormat:#"Unable to turn on %#. Use the \"Settings\" app to enable these notifications.", [UAPush pushTypeString:disabledTypes]];
NSString *errorTitle = #"Error";
UIAlertView *someError = [[UIAlertView alloc] initWithTitle:errorTitle
message:errorMessage
delegate:nil
cancelButtonTitle:okStr
otherButtonTitles:nil];
[someError show];
[someError release];
}
}
*/
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error {
UALOG(#"Failed To Register For Remote Notifications With Error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UALOG(#"Received remote notification: %#", userInfo);
// Get application state for iOS4.x+ devices, otherwise assume active
UIApplicationState appState = UIApplicationStateActive;
if ([application respondsToSelector:#selector(applicationState)]) {
appState = application.applicationState;
}
[[UAPush shared] handleNotification:userInfo applicationState:appState];
[[UAPush shared] resetBadge]; // zero badge after push received
}
- (void)applicationWillTerminate:(UIApplication *)application {
[UAirship land];
}
Its pretty the same like before, but given from UA. Then i copied the files from the other sources folder from the Push Sample into my phonegap folder Supported Files including the AirshipConfig.plist. Also I set the Header Search Paths in the Build Settings to the Airship folder, what i copied before into the xCode project folder.
Now I get the error (6) "Use of undeclared identifier 'UAPush'" in the AppDeledate.m file. What can I do now?
Thanks for some help...
You need to import both UAirship.h & UAPush.h in your AppDelegate.m
#import "MainViewController.h"
#import "UAirship.h"
#import "UAPush.h"
This will get rid of your undeclared identifier issue. Silly Urban Airship forgot to put this in their Documentation
Have a look at Xtify push services, PhoneGap plugin is fully supported:
iOS:
http://developer.xtify.com/display/sdk/PhoneGap+for+iOS+Xtify+Integration+Guide
Android:
http://developer.xtify.com/display/sdk/PhoneGap+for+Android+Xtify+Integration+Guide