I used Pushbots to configure push notifications for my app. After I get the notification, I am able to put it into a UITableview. However the notification only appears after the user restarts the app. Is there a way to immediately add the notification text after the user gets it, or when the user clicks the notification?
In my AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[Pushbots sharedInstanceWithAppId:#"--myAppid--"];
[[Pushbots sharedInstance] receivedPush:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// This method will be called everytime you open the app
// Register the deviceToken on Pushbots
[[Pushbots sharedInstance] registerOnPushbots:deviceToken];
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(#"Notification Registration Error %#", [error userInfo]);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//Handle notification when the user click it while app is running in background or foreground.
[[Pushbots sharedInstance] receivedPush:userInfo];
//NSLog(#"UserInfo: %#", userInfo);
NSString *msg = [userInfo valueForKey:#"aps"];
NSString *alertMsg = [msg valueForKey:#"alert"];
//NSLog(#"Push Notification:%#",alertMsg);
[[NSUserDefaults standardUserDefaults]setObject:alertMsg forKey:#"ReceivedNotifications"];
NSLog(#"Alert: %#", alertMsg);
}
In my ViewController.m:
#import "ViewController.h"
#interface ViewController () <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *notifTableView;
#end
#implementation ViewController
{
NSMutableArray *notif;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.notifTableView.dataSource = self;
self.notifTableView.delegate = self;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *checkAlert = [[NSString alloc] init];
checkAlert = [defaults stringForKey:#"ReceivedNotifications"];
NSLog(#"Alert Message: %#", checkAlert);
notif = [NSMutableArray arrayWithObjects:checkAlert, nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [notif count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [notif objectAtIndex:indexPath.row];
return cell;
}
In your ViewController viewDidLoad method start listen to a NSNotification as below,
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"TestNotification"
object:nil];
Add this receiveNotification to your ViewController as well. Inside this if condition you can reload the TableView.
- (void) receiveNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
}
Don't forget to remove the notification when you dealloc the ViewController,
[[NSNotificationCenter defaultCenter] removeObserver:self];
Then from your AppDelegate once you receive a notification, post a Notification to TestNotification name
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:nil]; //You can set object as nil or send the object you want to get from the ViewController
try to use NSNoticationCenter same as DilumN said in his answer , when you receive the notification then reload the tableview in that method.
Related
I am trying to establish voip call through two different apps. Lets assume one is seller and another is customer. Seller app can only call, and customer app can only receive call. I have setup two apps with sinch applicationKey, secret, userID etc. As I want to receive call in customer app, I have generated VOIP certificate in Apple Dev Account for customer app's bundle id. And I have uploaded that certificate(p12) in Sinch Dashboard. I am using Managed Push in customer app.
But I am unable to receive push or calls in customer app.
I tried changing the bundle id of the two apps. When I keep the bundle id same for the two apps, it works like charm.
My question is, How can I make voip calls between two different apps with different bundle ids?
Here is my AppDelegate.m file codes, which works as it should when the bundle id is same:
#import "SINCallKitProvider.h"
#import "CallViewController.h"
#interface AppDelegate () <SINClientDelegate, SINCallClientDelegate, SINManagedPushDelegate>
#property (nonatomic, readwrite, strong) id<SINManagedPush> push;
#property (nonatomic, readwrite, strong) SINCallKitProvider *callKitProvider;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"didFinishLaunchingWithOptions:");
[Sinch setLogCallback:^(SINLogSeverity severity, NSString *area, NSString *message, NSDate *timestamp) {
NSLog(#"[%#] %#", area, message);
}];
self.push = [Sinch managedPushWithAPSEnvironment:SINAPSEnvironmentAutomatic];
self.push.delegate = self;
[self.push setDesiredPushType:SINPushTypeVoIP];
self.callKitProvider = [[SINCallKitProvider alloc] init];
void (^onUserDidLogin)(NSString *) = ^(NSString *userId) {
[self initSinchClientWithUserId:userId];
};
[[NSNotificationCenter defaultCenter]
addObserverForName:#"UserDidLoginNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSString *userId = note.userInfo[#"userId"];
[[NSUserDefaults standardUserDefaults] setObject:userId forKey:#"userId"];
[[NSUserDefaults standardUserDefaults] synchronize];
onUserDidLogin(userId);
}];
[[NSNotificationCenter defaultCenter] addObserverForName:#"UserDidLogoutNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
_client = nil;
}];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
id<SINCall> call = [_callKitProvider currentEstablishedCall];
// If there is one established call, show the callView of the current call when
// the App is brought to foreground. This is mainly to handle the UI transition
// when clicking the App icon on the lockscreen CallKit UI.
if (call) {
UIViewController *top = self.window.rootViewController;
while (top.presentedViewController) {
top = top.presentedViewController;
}
// When entering the application via the App button on the CallKit lockscreen,
// and unlocking the device by PIN code/Touch ID, applicationWillEnterForeground:
// will be invoked twice, and "top" will be CallViewController already after
// the first invocation.
if (![top isMemberOfClass:[CallViewController class]]) {
[top performSegueWithIdentifier:#"callView" sender:call];
}
}
}
#pragma mark -
- (void)initSinchClientWithUserId:(NSString *)userId {
if (!_client) {
_client = [Sinch clientWithApplicationKey:#"<My key>"
applicationSecret:#"<My secret>"
environmentHost:#"clientapi.sinch.com"
userId:userId];
_client.delegate = self;
_client.callClient.delegate = self;
[_client setSupportCalling:YES];
[_client enableManagedPushNotifications];
_callKitProvider.client = _client;
[_client start];
// [_client startListeningOnActiveConnection];
}
}
- (void)handleRemoteNotification:(NSDictionary *)userInfo {
if (!_client) {
NSString *userId = [[NSUserDefaults standardUserDefaults] objectForKey:#"userId"];
if (userId) {
[self initSinchClientWithUserId:userId];
}
}
[self.client relayRemotePushNotification:userInfo];
}
#pragma mark - SINManagedPushDelegate
- (void)managedPush:(id<SINManagedPush>)managedPush
didReceiveIncomingPushWithPayload:(NSDictionary *)payload
forType:(NSString *)pushType {
NSLog(#"didReceiveIncomingPushWithPayload: %#", payload.description);
// Since iOS 13 the application must report an incoming call to CallKit if a
// VoIP push notification was used, and this must be done within the same run
// loop as the push is received (i.e. GCD async dispatch must not be used).
// See https://developer.apple.com/documentation/pushkit/pkpushregistrydelegate/2875784-pushregistry .
[self.callKitProvider didReceivePushWithPayload:payload];
dispatch_async(dispatch_get_main_queue(), ^{
[self handleRemoteNotification:payload];
[self.push didCompleteProcessingPushPayload:payload];
});
}
#pragma mark - SINCallClientDelegate
- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
// Find MainViewController and present CallViewController from it.
UIViewController *top = self.window.rootViewController;
while (top.presentedViewController) {
top = top.presentedViewController;
}
[top performSegueWithIdentifier:#"callView" sender:call];
}
- (void)client:(id<SINClient>)client willReceiveIncomingCall:(id<SINCall>)call {
[self.callKitProvider willReceiveIncomingCall:call];
}
#pragma mark - SINClientDelegate
- (void)clientDidStart:(id<SINClient>)client {
NSLog(#"Sinch client started successfully (version: %#)", [Sinch version]);
}
- (void)clientDidFail:(id<SINClient>)client error:(NSError *)error {
NSLog(#"Sinch client error: %#", [error localizedDescription]);
}
#end
How to set badge for UIBarButtonItem from Appdelegate (whenever push notification comes) if UITabbarcontroller is not the rootviewcontroller ?
I have a LoginViewController and a PinViewController before UITabbarcontroller. I'm setting LoginViewController as rootviewcontroller if user has not logged in and PinViewController as rootviewcontroller if user has already logged in. But I found that we could set badge for UIBarButtonItem from Appdelegate only if the rootviewcontroller is UITabbarcontroller.
Can anyone help me with this?
You can manage it by Posting Notifications
// In App Delegate Class
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSNumber *count = [NSNumber numberWithInt:5]; // This is static...
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:count
forKey:#"count"];
application.applicationIconBadgeNumber = 0;
if (application.applicationState == UIApplicationStateActive)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"getPushNotification" object:dataDict];
}
}
In Controller where you want to update badge count on bar.
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateBadgeCount:)
name:#"getPushNotification"
object:nil];
}
- (void)updateBadgeCount:(NSNotification *)note {
NSDictionary *theData = [note userInfo];
if (theData != nil) {
NSNumber *n = [theData objectForKey:#"count"];
// Do your stuff here...
}
}
Thanks.
When iPhone app is closed totally i.e. not even in background, then how APNS handling can be done.
e.g. Store APNS Data in sqlite when app is completely closed.
in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (launchOptions)
{ //launchOptions is not nil
NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
userInfoDic = userInfo;
if (apsInfo)
{ //apsInfo is not nil
[self performSelector:#selector(postNotificationToPresentPushMessagesVC)
withObject:nil
afterDelay:1];
}
}
return YES;
}
-(void)postNotificationToPresentPushMessagesVC
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"recievePush" object:userInfoDic];
}
in all VC:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(recievePush:) name:#"recievePush" object:nil];
}
- (void) recievePush : (NSNotification *) notif
{
NSDictionary *dict = notif.object;
// do something with message data
}
I handle push notification when the screen is on by automatically push to a detailViewController. It works fine when there is one or two push notification as I can push each detailViewController on top of each other and pop it back. However, app crash when I have to pop back more than two detailViewControllers. It happens only in iOS 7+.
Set notification Id
- (void)application:(UIApplication *)app didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if(app.applicationIconBadgeNumber!=0)
{
app.applicationIconBadgeNumber = app.applicationIconBadgeNumber - 1;
}
NSString *aps =[NSString stringWithFormat:#"%#",[userInfo objectForKey:#"id"]];
if (app.applicationState == UIApplicationStateActive)
{
NSDictionary *dict = [NSDictionary dictionaryWithObjects:#[[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]] forKeys:#[#"notifyText"]];
[arrNotificationData addObject:dict];
[self showNotificationInActiveMode:[[userInfo objectForKey:#"aps"] objectForKey:#"alert"]];
}
if ([aps isEqualToString:#"1"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"2"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"3"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
if ([aps isEqualToString:#"4"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}if ([aps isEqualToString:#"5"])
{
[UserDefault setpushnotificationid:[aps intValue]];
}
}
Use singleton class as base class and check for ID and the push and pop the view.
#interface CustomViewController ()
#end
#implementation CustomViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(appBecomeActive)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
-(void)appBecomeActive
{
int val=[UserDefault getpushnotificationid];
if(val!=0){
[self checkforpushnotification];
}
}
-(void)checkforpushnotification
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
int val=[UserDefault getpushnotificationid];
[UserDefault setpushnotificationid:0];
//.: if current view is profile or setting just dismiss it.because they are present
switch (val)
{
case 1:
{
if( [self checkIfControllerExist:[DealsViewController class]])
{
return;
}else{
detailViewController *VC = (detailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"VCView"];
[self.navigationController pushViewController:VC animated:YES];
}
}
break;
}
}
Now use bace class in your class
#interface detailViewController : CustomViewController
I have just added push notifications to my app. I'm wanting to have so that when a user opens the app from a notification, it will open a specific view controller and not my rootViewController. Here is my AppDelegate:
#import "KFBAppDelegate.h"
#import "KFBViewController.h"
#import "AboutUs.h"
#import "ContactUs.h"
#import "KYFB.h"
#import "KFBNavControllerViewController.h"
#import "KFBTabBarViewController.h"
#import "RSFM.h"
#import "LegislatorInfo.h"
#import "Events.h"
#import "ActionAlertsViewController.h"
#import "UAirship.h"
#import "UAPush.h"
#import "UAAnalytics.h"
#implementation KFBAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// This prevents the UA Library from registering with UIApplcation by default when
// registerForRemoteNotifications is called. This will allow you to prompt your
// users at a later time. This gives your app the opportunity to explain the benefits
// of push or allows users to turn it on explicitly in a settings screen.
// If you just want everyone to immediately be prompted for push, you can
// leave this line out.
// [UAPush setDefaultPushEnabledValue:NO];
//Create Airship options dictionary and add the required UIApplication launchOptions
NSMutableDictionary *takeOffOptions = [NSMutableDictionary dictionary];
[takeOffOptions setValue:launchOptions forKey:UAirshipTakeOffOptionsLaunchOptionsKey];
// Call takeOff (which creates the UAirship singleton), passing in the launch options so the
// library can properly record when the app is launched from a push notification. This call is
// required.
//
// Populate AirshipConfig.plist with your app's info from https://go.urbanairship.com
[UAirship takeOff:takeOffOptions];
// Set the icon badge to zero on startup (optional)
[[UAPush shared] resetBadge];
// Register for remote notfications with the UA Library. This call is required.
[[UAPush shared] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)];
// Handle any incoming incoming push notifications.
// This will invoke `handleBackgroundNotification` on your UAPushNotificationDelegate.
[[UAPush shared] handleNotification:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]
applicationState:application.applicationState];
// self.tabBarController = [[UITabBarController alloc] initWithNibName:#"KFBViewController" bundle:nil];
KFBViewController *rootView = [[KFBViewController alloc] initWithNibName:#"KFBViewController" bundle:nil];
KFBNavControllerViewController *navController = [[KFBNavControllerViewController alloc] initWithRootViewController:rootView];
navController.delegate = rootView;
UIViewController *aboutUs = [[AboutUs alloc] initWithNibName:#"AboutUs" bundle:nil];
KFBNavControllerViewController *navController1 = [[KFBNavControllerViewController alloc] initWithRootViewController:aboutUs];
UIViewController *contactUs = [[ContactUs alloc] initWithNibName:#"ContactUs" bundle:nil];
KFBNavControllerViewController *navController2 = [[KFBNavControllerViewController alloc] initWithRootViewController:contactUs];
UIViewController *kyfb = [[KYFB alloc] initWithNibName:#"KYFB" bundle:nil];
KFBNavControllerViewController *navController3 = [[KFBNavControllerViewController alloc] initWithRootViewController:kyfb];
// UIViewController *rsfm = [[RSFM alloc] initWithNibName:#"RSFM" bundle:nil];
// KFBNavControllerViewController *navController4 = [[KFBNavControllerViewController alloc] initWithRootViewController:rsfm];
// UIViewController *li = [[LegislatorInfo alloc] initWithNibName:#"LegislatorInfo" bundle:nil];
// KFBNavControllerViewController *navController5 = [[KFBNavControllerViewController alloc] initWithRootViewController:li];
// UIViewController *events = [[Events alloc] initWithNibName:#"Events" bundle:nil];
// KFBNavControllerViewController *navController6 = [[KFBNavControllerViewController alloc] initWithRootViewController:events];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//self.viewController = [[KFBViewController alloc] initWithNibName:#"KFBViewController" bundle:nil];
//self.window.rootViewController = self.viewController;
self.tabBarController = [[KFBTabBarViewController alloc] init];
self.tabBarController.viewControllers = #[navController, navController1, navController2, navController3];
// self.tabBarController.customizableViewControllers = nil;
self.window.rootViewController = self.tabBarController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
UA_LDEBUG(#"Application did become active.");
// Set the icon badge to zero on resume (optional)
[[UAPush shared] resetBadge];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[UAirship land];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Updates the device token and registers the token with UA.
[[UAPush shared] registerDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error
{
UA_LERR(#"Failed To Register For Remote Notifications With Error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UA_LINFO(#"Received remote notification: %#", userInfo);
// Send the alert to UA so that it can be handled and tracked as a direct response. This call
// is required.
[[UAPush shared] handleNotification:userInfo applicationState:application.applicationState];
// Optionally provide a delegate that will be used to handle notifications received while the app is running
// [UAPush shared].delegate = your custom push delegate class conforming to the UAPushNotificationDelegate protocol
// Reset the badge after a push received (optional)
[[UAPush shared] resetBadge];
}
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
#end
And here is the view controller I want to open when opening a notification:
#import "ActionAlertsViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#import "CustomCellBackground.h"
#implementation ActionAlertsViewController
{
UIActivityIndicatorView *loadingIndicator;
}
#synthesize webViewController;
- (void)viewDidLoad
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.title = #"Action Alerts";
loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loadingIndicator.center = CGPointMake(160, 160);
loadingIndicator.hidesWhenStopped = YES;
[self.view addSubview:loadingIndicator];
[loadingIndicator startAnimating];
// UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
// refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to Refresh"];
// [refresh addTarget:self action:#selector(refreshView:)forControlEvents:UIControlEventValueChanged];
// self.refreshControl = refresh;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"%# found a %# element", self, elementName);
if ([elementName isEqual:#"channel"])
{
// If the parser saw a channel, create new instance, store in our ivar
channel = [[RSSChannel alloc]init];
// Give the channel object a pointer back to ourselves for later
[channel setParentParserDelegate:self];
// Set the parser's delegate to the channel object
[parser setDelegate:channel];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return 0;
NSLog(#"channel items %d", [[channel items]count]);
return [[channel items]count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
cell.textLabel.font=[UIFont systemFontOfSize:16.0];
}
RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];
[[cell textLabel]setText:[item title]];
cell.backgroundView = [[CustomCellBackground alloc] init];
cell.selectedBackgroundView = [[CustomCellBackground alloc] init];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.highlightedTextColor = [UIColor darkGrayColor];
return cell;
}
- (void)fetchEntries
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc]init];
// Construct a URL that will ask the service for what you want -
// note we can concatenate literal strings together on multiple lines in this way - this results in a single NSString instance
NSURL *url = [NSURL URLWithString:#"http://kyfbnewsroom.com/category/public-affairs/notifications/feed/"];
// Put that URL into an NSURLRequest
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
[self fetchEntries];
}
return self;
}
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
/* We are just checking to make sure we are getting the XML
NSString *xmlCheck = [[NSString alloc]initWithData:xmlData encoding:NSUTF8StringEncoding];
NSLog(#"xmlCheck = %#", xmlCheck);*/
[loadingIndicator stopAnimating];
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];
// Give it a delegate - ignore the warning here for now
[parser setDelegate:self];
//Tell it to start parsing - the document will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Reload the table.. for now, the table will be empty
NSMutableArray *notActionAlerts = [NSMutableArray array];
for (RSSItem *object in channel.items) {
if (!object.isActionAlert) {
[notActionAlerts addObject:object];
}
}
for (RSSItem *object in notActionAlerts) {
[channel.items removeObject:object];
}
[[self tableView]reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
connection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view with this error displayed
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Push the web view controller onto the navigation stack - this implicitly creates the web view controller's view the first time through
// [[self navigationController]pushViewController:webViewController animated:YES];
[self.navigationController pushViewController:webViewController animated:NO];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
// Set the title of the web view controller's navigation item
// [[webViewController navigationItem]setTitle:[entry title]];
}
/*
-(void)refreshView:(UIRefreshControl *)refresh
{
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Refreshing data..."];
// custom refresh logic would be placed here...
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM d, h:mm a"];
NSString *lastUpdated = [NSString stringWithFormat:#"Last updated on %#",[formatter stringFromDate:[NSDate date]]];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdated];
[refresh endRefreshing];
}
*/
#end
Here is the chunk of code I've added to my didFinishLaunchingWithOptions method. I've gotten almost everything working. The web views work now when selecting a row and the navigation bar is there and seemingly works as it should. The only trouble I'm having now is getting the tab bar to show up. Here is the chunk of code I'm currently using.
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification)
{
ActionAlertsViewController *actionAlerts = [[ActionAlertsViewController alloc] initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[actionAlerts setWebViewController:wvc];
KFBNavControllerViewController *navController7 = [[KFBNavControllerViewController alloc] initWithRootViewController:actionAlerts];
[self.window.rootViewController presentViewController:navController7 animated:NO completion:nil];
}
You could post a notification yourself when you receive a remote notification and by registering the viewcontroller to this notification, you could open a particular viewController once notification is received.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
[[NSNotificationCenter defaultCenter] postNotificationName:#"pushNotification" object:nil userInfo:userInfo];
}
In your FirstViewController.m register for listening to this notification.
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(pushNotificationReceived) name:#"pushNotification" object:nil];
}
Inside the method you could open particular viewController
-(void)pushNotificationReceived{
[self presentViewController:self.secondViewController animated:YES completion:nil];
}
Finally un-register current viewController from notification in dealloc method
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
If the app is opened from a notification, either of the two methods from your app delegate will be called
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
OR
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
In case of the latter, the launchOptions will let you know if the app was launched due to a remote notification or some other reason (see Launch Option Keys here)
Put in a check in these methods so that the specific viewcontroller will be opened if the app is launched from a notification.
You can do some thing like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
// If application is launched due to notification,present another view controller.
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification)
{
NotificationViewController *viewController = [[NotificationViewController alloc]initWithNibName:NSStringFromClass([NotificationViewController class]) bundle:nil];
[self.window.rootViewController presentModalViewController:viewController animated:NO];
[viewController release];
}
return YES;
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NotificationViewController *viewController = [[NotificationViewController alloc]initWithNibName:NSStringFromClass([NotificationViewController class]) bundle:nil];
[self.window.rootViewController presentModalViewController:viewController animated:NO];
[viewController release];
}