How to initialise a VC or Class iOS, ObjectiveC - ios

When a button is clicked at FirstVC, it will pass data and trigger SecondVC using NSNotificationCenter
During initial launch of the app, because SecondVC has not been initialize yet, so data cannot be passed to SecondVC. NSNotificationCenter cannot function properly. Only after SecondVC has been initialize, NSNotificationCenter will function correctly.
So I need to initialise SecondVC somewhere. Will it be at - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions?
Or how do I programatically call the tab of SecondVC.
FirstVC
#import "Search.h"
#import "Classes.h"
#import "MyTabBarController.h"
#interface Search(){
AppDelegate *appDelegate;
CERangeSlider* _rangeSlider;
NSString *sURL, *strResult, *sRemaining, *sStartTime, *sEndTime, *sSelectedLat, *sSelectedLong;
}
#end
#implementation Search
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:sURL forKey:#"theURL"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"toClasses" object:nil userInfo:userInfo];
}
#end
Second VC
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(receiveTestNotification:)
name:#"toClasses"
object:nil];
dtDate = [[NSMutableArray alloc] init]; //=== Mutable array to store the dates generated
self.currentPageIndex = 0;
[self setupSegmentButtons];
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/YYYY"];
sDtDate = [dateFormatter stringFromDate:now];
[self LoadClasses];
}
-(void)viewWillAppear:(BOOL)animated {
//--- Hide the Top Navigation Controller Bar at the current View
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}
//--- Top Navigation Controller reappear on the next VC
-(void)viewDidDisappear:(BOOL)animated{
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
-(void) receiveTestNotification:(NSNotification*)notification
{
if ([notification.name isEqualToString:#"toClasses"])
{
NSDictionary* userInfo = notification.userInfo;
NSLog (#"Successfully received userInfo! %#", userInfo);
NSString* sFromSearch = [NSString stringWithFormat: #"%#", userInfo];
NSLog (#"Successfully received test notification! %#", sFromSearch);
}
}

In my opinion, you don't need to use notification or singleton on this case.
Simply, get SecondViewController from self.tabBarController and call the method.
First VC
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
UINavigationController* secondNav = (UINavigationController*)self.tabBarController.viewControllers[1];
SecondViewController* secondViewController = [secondNav.viewControllers firstObject];
[secondViewController handleString:sURL];
}
Second VC
- (void)handleString:(NSString*)string {
// Do whatever you want with string passed from First VC
}

You added observer in viewDidLoad, so it will not work even you create it before user tap on button and send notification. because observer will not be registered. I advise you not use observer to send data in this case. you can save this data elsewhere and use it when seconVC will load. for example in singleton object.
your Singleton object looks like this:
Interface:
#interface DataManager : NSObject
#property (nonatomic, strong) NSDictionary *userInfo;
+ (DataManager *) getInstance;
#end
Implementation:
#implementation DataManager
+ (DataManager *) getInstance {
static DataManager *appManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
appManager = [[DataManager alloc] init];
});
return appManager;
}
#end
Now you can access this object where you want and you can assured that only one instance is created.
here is your button click method:
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:sURL forKey:#"theURL"];
[DataManager getInstance].userInfo = userInfo;
}
and your viewDidLoad in secondVC
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *userInfo = [DataManager getInstance].userInfo;
}

Related

How to pass data to viewController without creating its object

I am creating a iOS static library in which user will pass the name of the Viewontroller and some parameters inside the push and I am getting these details in didReceiveRemoteNotification and from here I got a string suppose NSString *vcName = #"ViewController2" and parameter suppose NSString *param1= #"UserName" NSString *param2= #"email" now I want to pass these parameters to the viewController Which name's string is received from push. But I don't want to write #import ViewController2.
I am able to redirect to ViewController2 without importing it but don't know how to pass these parameters to ViewController2
I can redirect to the viewController from the following code.
NSString *vcName = #"ViewController2";
NSString *param1= #"UserName";
NSString *param2= #"user_email";
UIStoryboard * storyboard = [[[UIApplication sharedApplication] keyWindow] rootViewController].storyboard;
UIViewController *vcToOpen = [storyboard instantiateViewControllerWithIdentifier:vcName]];
vcToOpen.modalPresentationStyle =UIModalPresentationFullScreen;
[[[[UIApplication sharedApplication]keyWindow] rootViewController] presentViewController:vcToOpen animated:YES completion:nil];
Now I want to get these two parameter's value in ViewController2. Can anybody help me how to do it. without writing #import ViewController2 because app can has many ViewControllers and vcName can be any of them.
AppDelegate.h
-(NSString *)getEmail;
-(NSString *)getName;
-(void)setEmail:(NSString *)email Name:(NSString *)name;
+(AppDelegate *)sharedAppDelegate;
AppDelegate.m
#interface AppDelegate ()
{
NSString *strEmail, *strName;
}
-(NSString *)getEmail
{
return strEmail;
}
-(NSString *)getName
{
return strName;
}
-(void)setEmail:(NSString *)email Name:(NSString *)name
{
strEmail = email;
strName = name;
}
+(AppDelegate *)sharedAppDelegate
{
return (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
ViewController1.m
#import "AppDelegate.h"
-(void)gotoViewController2
{
[[AppDelegate sharedAppDelegate] setEmail:#"email#gmail.com" Name:#"name1234"];
[self performSegueWithIdentifier:#"segueToViewController2" sender:nil];
}
ViewController2.m
#import "AppDelegate.h"
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *name = [[AppDelegate sharedAppDelegate]getName];
NSString *email = [[AppDelegate sharedAppDelegate]getEmail];
NSLog(#"name = %# and email = %#",name, email); //name = name1234 and email = email#gmail.com
}
Storing values in your app delegate is just messy.
Each one of your UIViewControllers that could be launched from a push notification could conform to a custom 'launch' protocol.
Each UIViewController e.g. 'UIViewController2' would conform to this protocol.
You could write the protocol like this:
#protocol LaunchProtocol <NSObject>
- (void) launchParams:(NSDictionary *)params;
#end
Each UIViewController could conform to this protocol, like so:
#interface ViewController2 : UIViewController <LaunchProtocol>
#end
#implementation ViewController2
- (void) launchParams:(NSDictionary *)params {
}
#end
Your app delegate only needs to know about the protocol, it doesn't care about your UIViewControllers.
When you get a push notification you check if the view controller conforms to the launch protocol.
...
vcToOpen.modalPresentationStyle =UIModalPresentationFullScreen;
if ([vcToOpen conformsToProtocol:#protocol(LaunchProtocol)]) {
UIViewController <LaunchProtocol> *launchController = (UIViewController <LaunchProtocol> *) vcToOpen;
NSDictionary* params = #{ /* create your param dict */ };
[launchController launchParams:params];
}
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:vcToOpen animated:YES completion:nil];
...
You would include the information from the push notification in the 'params' dict, and the UIViewController would extract what information it needs from it in launchParams:
- (void) launchParams:(NSDictionary *)params {
NSLog(#"Username: %#", params[#"username"]);
}
Actually you can use Singleton design pattern to achieve this. Create one shared instance class to store the values.
+ (instancetype)sharedInstance
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
create properties inside the manager class which needs to be saved, then access the values from the manager class.

How to call a function that is found in a specific view controller at the moment the application is launched?

I have some functions in my SecondViewController.m file and I want to call these functions when the application is launched. I have tried to do it like this, but it’s not working.
I have put a print statement in the function to see if it is getting called or not and it appears that the print statement is executed correctly.
Here is the following code:
In SecondViewController.h:
#interface AlertsManagementController : UIViewController {
PushNotificationSettings *pushNotificationSettings;
IBOutlet UISwitch *switch1;
IBOutlet UISwitch *switch2;
}
#property (nonatomic, retain) PushNotificationSettings *pushNotificationSettings;
In SecondViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (projectAppDelegate *)[[UIApplication sharedApplication] delegate];
pushNotificationSettings = [[PushNotificationSettings alloc] init];
NSDictionary * settings = [pushNotificationSettings getPushSettings];
}
-(void)modificationPush
{
if (switch1.on && switch2.on)
[switch2 setOn:NO];
printf("Function 1 executed!");
}
-(void)sendTokenFunc{
NSMutableDictionary *preferences1 = [[NSMutableDictionary alloc] init];
if (switch1.on)
[preferences1 setObject:#"1" forKey:#“switch1”];
else
[preferences1 setObject:#"0" forKey:#“switch1”];
if (switch2.on)
[preferences1 setObject:#"1" forKey:#“switch2”];
else
[preferences1 setObject:#"0" forKey:#“switch2”];
[pushNotificationSettings savePushSettingsWithDictionary:preferences1];
[preferences1 release];
[appDelegate uploadToken:[appDelegate tokenValue]];
printf("Function 2 executed!");
}
In appDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
SecondViewController * vc = [[SecondViewController alloc]init];
[vc modificationPuch];
[vc sendTokenFunc];
}
This can be done by using NSNotificationCenter.
First go to your SecondViewController.m file and in viewDidLoad write the following code.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myNotification:) name:#"myNotification" object:nil];
Then outside viewDidLoad make a function myNotification. I will show you the eg below
-(void)myNotification:(NSNotification*)notification
{
//write the code you wanna excecute when the app opens here
}
Go to appDeligate.m and write this code in application didFinishLaunchingWithOptions
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:self userInfo:nil];
Thank you,
Happy coding;)
But if SecondViewController didn't inited, you must get EXC_BAD_ACCESS :)

How to edit NSMutableArray in other Class

I have NSMutableArray in "AppDelegate.h"
#property (strong, nonatomic) NSMutableArray *myArray;
and "AppDelegate.m"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.myArray = [[NSMutableArray alloc] init];
return YES;
}
In UITableViewController i add objects in NSMutableArray
- (IBAction)AddComment:(UIBarButtonItem *)sender
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
SectionObject *sectionObject = [[SectionObject alloc] init];
sectionObject.id = (NSInteger*)appDelegate.myArray.count;
sectionObject.name = [NSString stringWithFormat:#"New object %i",appDelegate.myArray.count];
[appDelegate.myArray addObject:sectionObject];
[self.tableView reloadData];
}
To edit the object I pass other UITableViewController objects from the array controller
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navController = segue.destinationViewController;
ExerciseTableViewController *controller = (ExerciseTableViewController *)navController;
controller.contactdb = [appDelegate.myArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
}
When i am going back to write
-(void)viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
self.contactdb.name = self.nameTextField.text;
}
[super viewWillDisappear:animated];
}
I receive an error 'EXC_BAD_ACCESS'. If i not edit self.contactdb.name, I dont have error. How can i edit object in other controller?
Your if-statement:
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound)
basically guarantees your view controller has already been removed from the navigation stack. That's why you get a EXC_BAD_ACCESS error when trying to access properties from that view controller. You should place your self.contactdb.name = self.nameTextField.text statement somewhere else.

TableView not showing new data loaded from plist after dismissing from other view

My First View is a UIViewController i have a UITable View in it and it works just fine.
From the first view i push another view, in that view i select a group name then the view dismiss, what i want is when i select the group name from the second view the first view loads the values of that group name to the table view, this is the code i use and its not working
the second view code
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = [[ViewController alloc] init];
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
keyValue is NSString that been set on tableView didSelectRowAtIndexPath
the first view
- (IBAction)ReceivedGroup:(id)sender {
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:groupName];
nameArray = [[NSMutableArray alloc] init];
[nameArray addObjectsFromArray:tempArray];
[nameTable reloadData];
NSLog(#"Group Name : %#",groupName);
NSLog(#"Array : %#",nameArray);
}
groupName is NSString
In the log i get the groupName and the nameArray printed
but the tableView is empty.
EDIT: I fixed the problem and posted my answer
Your viewcontroller "theInstance" will be deallocated immediately after calling sendNames: so nothing's gonna happen. You should rather pass a pointer of your first viewcontroller to your second viewcontroller (e.g. set it as a property) and perform all operations on this viewcontroller.
subclass UITableViewController
#interface SecondViewController : UITableViewController
#property (nonatomic, strong) ViewController *firstViewController;
#end
if using storyboard segues implement in your first viewcontroller :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
((SecondViewController *) segue.destinationViewController).firstViewController = self;
}
sendNames: should then look like this:
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = self.firstViewController;
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
I Fixed it by sending the keyValue using NSNotificationCenter
Here is my code now
For The Second View
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:keyValue];
[self dismissViewControllerAnimated:YES completion:nil];
}
Then On The First View
- (void)receiveNotification:(NSNotification *)notification {
NSString *Key = [notification object];
nameArray = [[NSMutableArray alloc] init];
[nameArray removeAllObjects];
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:Key];
[nameArray addObjectsFromArray:tempArray];
[self.nameTable reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[nameTable numberOfRowsInSection:0] - 1 inSection:0];
[nameTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveNotification:) name:#"RG" object:nil];
}

Open Specific View when Opening App from Notification

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];
}

Resources