I'm trying to find an updated doc that includes any info / code samples on the new interactive push notifications. The guide I found on Local & Remote Push Notifications still shows the payload size is 256 bytes. My understanding is that in ios8 that limit has been raised to 2k.
I'm also trying to find documentation on how to add custom buttons to make my notifciations interactive. I don't see very much in the push notification programming guide.
How do I setup a category to add custom buttons with colors? Any documentation on this would be useful.
You can create interactive notifications by defining the action buttons in iOS8.
Create UIMutableUserNotificationAction buttons.
Then Create UIMutableUserNotificationCategory and group above actions into category.
Add all categories into set.
Create UIUserNotificationSettings with this category set.
Register notifications with this settings
Add category field in push payload and send notification
Please find below the sample code:
- (void) registerRemoteNotificationWithActions{
//1. Create action buttons..:)
UIMutableUserNotificationAction *shareAction = [[UIMutableUserNotificationAction alloc] init];
shareAction.identifier = #"SHARE_IDENTIFIER";
shareAction.title = #"Share";
shareAction.activationMode = UIUserNotificationActivationModeForeground;
shareAction.destructive = NO;
shareAction.authenticationRequired = YES;
//2. Then create the category to group actions.:)
UIMutableUserNotificationCategory *shareCategory = [[UIMutableUserNotificationCategory alloc] init];
shareCategory.identifier = #"SHARE_CATEGORY";
[shareCategory setActions:#[shareAction] forContext:UIUserNotificationActionContextDefault];
[shareCategory setActions:#[shareAction] forContext:UIUserNotificationActionContextMinimal];
//3. Then add categories into one set..:)
NSSet *categories = [NSSet setWithObjects:shareCategory, nil];
//4. Finally register remote notification with this action categories..:)
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
}
Sample payload format :
{
"aps": {
"badge": 1,
"alert": "Hello world!",
“category”: “SHARE_CATEGORY”
}
}
And handle the actions using the following method :
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
if ([identifier isEqualToString:#"SHARE_IDENTIFIER"] ){
}
}
You can check this link for more info.
This is a tutorial I found in youtube for custom action push notification. It is done in swift.
https://www.youtube.com/watch?v=Yh3lLpV1k_Y
Related
I'm using SWRevealViewController 2.3.0 in my project. My storyboard is designed as below:
http://i.stack.imgur.com/txv0G.png
When the app is not running (completely terminated) and a push notification comes, how to get the Detail view controller showed up with a Back button to go back Main view controller? Some notification values should have passed to the Detail view.
Thanks for any help.
What i am doing in this type of case is
you can check if launchOptions is not nil didFinishLaunchingWithOptions as
if (launchOptions)
{
NSDictionary *dic = [launchOptions objectForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"];
[[NSUserDefaults standardUserDefaults] setObject:[dic objectForKey:#"aps"] forKey:#"PushNotification"];
}
else
{
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"PushNotification"];
}
and save in user Defaults as i did.
Now simply When you are in mainViewController you can check it as
NSDictionary *notification = [[NSUserDefaults standardUserDefaults] objectForKey:#"PushNotification"];
if (notification)
{
// check the dictionary "Push Notification" Key Values that you are receiving to go in `DetailViewController`
// Now go to `DetailViewContoller` having your details from `PushNotification`by `performSegueWithIdentifier`
[self performSegueWithIdentifier:#"DetailViewController" sender:self];
// make this value nil for normal use
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"PushNotification"];
}
if you don't make this userDefaults value nil here, you can use it in DetailViewController too, but don't forget to make nil after use.
Using this way your BACK button should show in DetailViewController
I'm trying to create a split view app with multiple detail view controllers. I'm having trouble with the basic setup/skeleton of the app. First I tried using xcode's Master-Detail Application template. The problem is that the classes from the template look something like this:
MasterViewController.h
MasterViewController.m
DetailViewController.h
DetailViewController.m
But what I want is something like this:
MasterViewController.h
MasterViewController.m
TitleViewController.h
TitleViewController.m
DateViewController.h
DateViewController.m
...
I can't figure out how to get my view controllers to load when user selects a new row.
I also tried using the sample MultipleDetailViews app from Apple, but the sample app has multiple issues for me including the fact that it uses nib files, which I don't want.
Can anyone help? Is there some tutorial about how to set up a split view app with multiple detail view controllers (without nibs)? Thank you!
*response:
Thanks! Could you post the link for the BigNerdRanch one? I couldn't find it. Also, I couldn't follow the Raywenderlich one because it uses an older version of xcode. Following your sample project, I think I'm close, but I'm getting a "terminating with uncaught exeption...". Here's what I did:
Create new project from Master-Detail template.
Add files MyTableViewController.h and MyTableViewController.m.
In MasterViewController.m, set the number of sections to 1 and the number of rows to 2.
In MasterViewController.h add property "MyTableViewController *myTableViewController".
(When user clicks 1st row, detailViewController should show, when he clicks 2nd row, myTableViewController should show.)
In MasterViewController.m, change didSelectRowAtIndexPath to:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = [indexPath row];
if( row == 0 ) {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.detailViewController];
NSArray *vcs = [NSArray arrayWithObjects:[self navigationController],nav, nil];
[[self splitViewController] setViewControllers:vcs];
}
else {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.myTableViewController];
NSArray *vcs = [NSArray arrayWithObjects:[self navigationController],nav, nil];
[[self splitViewController] setViewControllers:vcs];
}
}
The project runs, but when I click on the 2nd row (row == 1) I get the exception.
*update 2
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
int row = [indexPath row];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
UINavigationController *detailNav = [delegate.splitController.viewControllers objectAtIndex: 1];
NSArray *viewControllers = nil;
switch (row) {
case 0:
viewControllers = [[NSArray alloc] initWithObjects: delegate.dateController, nil];
break;
case 1:
viewControllers = [[NSArray alloc] initWithObjects: delegate.repeatController, nil];
default:
break;
}
[delegate.splitController removeFromParentViewController];
detailNav.viewControllers = viewControllers;
[delegate.window addSubview: delegate.splitController.view];
}
There's actually a great tutorial by the BigNerdRanch on how to use UISplitViewControllers. Honestly, there's no difference between using them to push a different UIViewController as the Detail or Master viewController. They just need a reference to one another and when an event happens, you push a new viewController to one side or the other. I've attached a sample project below for you to reference.
sample project: link
Here's another tutorial on setting one up via Raywenderlich: link
So the following happenins inside a UITableViewController which is the MasterViewController.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// 1. get the controllers from the split view [master, detail]
let controllers = split.viewControllers
// 2. get nav controller for the detail + the current storyboard
let navigationController = controllers[controllers.count-1] as!
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// 3. create the appropriate view controller (vc) then just replace the navigation controllers root vc with your new one using 'navigationController.setViewControllers([vc] ...'
switch indexPath.row {
case 1:
let vc = storyboard.instantiateViewController(withIdentifier: "DetailTableViewController") as! DetailTableViewController
navigationController.setViewControllers([vc], animated: false)
case 2:
let vc = storyboard.instantiateViewController(withIdentifier: "DetailCollectionViewController") as! DetailCollectionViewController
navigationController.setViewControllers([vc], animated: false)
default:
let vc = storyboard.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
navigationController.setViewControllers([vc], animated: false)
break
}
}
You can do the same thing with segues. From the MasterViewController in the storyboard, drag a segue to a navigation controller and set the segue kind as a 'Show Detail (e.g. replace)'. Then from there in you didSelectRowAt you can call performSegue with identifier. Make sure that your segue has an 'Identifier'
Have a look at this video
I am using MKMapItem to launch Map app from within my app after the user taps 'Directions' button. The Map app comes up fine showing directions from current location to a address. But how do I go back to my app, If I no longer want to see Directions? Below is my code attached to IBAction.
Code:
- (IBAction)pressDirectionsButton:(id)sender {
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)])
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
NSString *addressString = [NSString stringWithFormat:#"%#,%#,%#,%#,%#",
self.currentlySelectedTemple.houseNumber,
self.currentlySelectedTemple.street,
self.currentlySelectedTemple.city,
self.currentlySelectedTemple.state,
self.currentlySelectedTemple.country];
[geocoder geocodeAddressString:addressString completionHandler:^(NSArray *placemarks, NSError *error) {
//Convert CLPlacemark to an MKPlacemark
CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc]
initWithCoordinate:geocodedPlacemark.location.coordinate addressDictionary:geocodedPlacemark.addressDictionary];
//Create a map item for geocoded address to pass to Maps app
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:geocodedPlacemark.name];
//Set Directions mode to Driving
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving};
//Get the "Current User Locations" MKMapItem
MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
//Pass the current location and destination map items to Maps app
[MKMapItem openMapsWithItems:#[currentLocationMapItem, mapItem] launchOptions:launchOptions];
}];
}
}
There is no way to go back to your app (programatically), as you are no longer in your app, but in the Maps app. After executing openMapsWithItems:launchOptions:, your App Delegate's applicationdDidEnterBackground: method is called.
Currently there is no way to use Mapkit to embed a map with directions within your app.
Can I make a button, that when I click it the phone makes a call to a certain number, or similarly sends an email to certain address with some pre-populated fields. I need this to work on iOS and Android too.
Yes, you can make a URL request actually that the phone understands to make a call. You just prefix it with tel. Same works for "mailto".
See this example: http://www.adobe.com/devnet/air/quick_start_as/quickstarts/qs_using_uris.html
see this the exact thing you all looking for
http://www.flextechie.com/my-first-flex-mobile-application-contact-mobile-app/
you can even download the source code
Just add following code on Button Click :
-(void) makeCall
{
NSString * mobileNumber = #"+9112345678";
UIDevice *device = [UIDevice currentDevice];
if ([[device model] isEqualToString:#"iPhone"] )
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#",mobileNumber]]];
}
else
{
UIAlertView *Notpermitted=[[UIAlertView alloc] initWithTitle:nil message:#"Your device doesn't support calling feature." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Notpermitted show];
}
}
I'm having some trouble understanding how all the "nuts and bolts" of the Master-Detail Application template works using Xcode 4.2 (without MainWindow.xib, as well as other changes). In "AppDelegate" we have the following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
return YES;
}
I see that the window is created programmatically instead of using the MainWindow.xib that was use in previous versions of Xcode in the beginning, as well as instantiating objects for both "Master" and "Detail" view controller classes that are provided with the template and using them for separate UINavigationControllers. Then the splitViewController property is assigned a new allocated UISplitViewController object assigning the detailViewController as the "delegate" and an array is created that contains both UINavigationControllers as "viewControllers." Then the window.rootViewController is assigned this splitViewController object.
The main questions I have are
1) Why do I need two "UINavigationControllers?" Couldn't I just create the "viewController" array using the "master" and "detail" view controllers themselves?"
2) What does it do setting the "detailViewController" as the "delegate?" What actually gets delegated?
3) And finally, if I wanted to push additional items onto the "DetailViewController" stack, would I just use the "DetailViewController" class to push using the "didSelectRow.." method, or would I need to do updates to self.splitViewController.viewControllers property instead?
1) Why do I need two "UINavigationControllers?" Couldn't I just create the "viewController" array using the "master" and "detail" view controllers themselves?"
You don't need. But it's a way. You have the ability to push the masterViewControlleras well as the detailViewController. Look at the layout in Storyboard. With using segue you can change the controllers on each side as you like.
2) What does it do setting the "detailViewController" as the "delegate?" What actually gets delegated?
The UISplitViewget's delegated. The detailViewController will take care of the interface changing in portrait and landscape mode. See UISplitViewDelegate in the documentation.
Showing and Hiding View Controllers
– splitViewController:shouldHideViewController:inOrientation:
– splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
– splitViewController:willShowViewController:invalidatingBarButtonItem:
– splitViewController:popoverController:willPresentViewController:
3) And finally, if I wanted to push additional items onto the "DetailViewController" stack, would I just use the "DetailViewController" class to push using the "didSelectRow.." method, or would I need to do updates to self.splitViewController.viewControllers property instead?
Yes you can push in the masterViewControllerwith the tableView selection. You can push either with the new controller on the masterViewControllerstack by pushing in the
- (void)viewDidAppear:(BOOL)animated
and you can push in any way you like. You don't have to update the self.splitViewController.viewControllers property. Maybe you have to set the delegate to your new detailViewController.