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.
Related
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;
}
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 :)
I am trying to copy the contents of one NSDictionary into a NSMutableDictionary.
This is what I have done so far.
#implementation RosterListController
- (void)newMessageReceived:(NSDictionary *)messageContent
{
self.messageDictionary = [[NSMutableDictionary alloc]initWithDictionary:messageContent]; // This is where I am copying
UIApplication *app = [UIApplication sharedApplication];
if (app.applicationState == UIApplicationStateActive)
{
UILocalNotification *localNotif = [[UILocalNotification alloc]init];
if (localNotif)
{
localNotif.alertAction = #"OK";
localNotif.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[app presentLocalNotificationNow:localNotif];
}
}
}
Then I handle this notification in appDelegate by showing a AlertView.After that is done..coming back to RosterViewController.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSLog(#"Cancel button presed");
}
else
{
if(chatView) // Chat ViewController
{
[chatView recvdMsg:self.messageDictionary];
}
else
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
chatView=(ChatViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"chatviewcontroller"];
NSMutableDictionary *buddy=[[NSMutableDictionary alloc]init];
// The break point stops the app here & shows buddy dictionary as nil.
==> [buddy setObject:[self.messageDictionary objectForKey:#"sender"] forKey:#"jid"];
// Originally it was messageContent dict from the parameter above that I used which worked fine..
//But since I need that dictionary in another method..I copied that dictionary into self.messageDictionary which also gets copied.
// However now the above line causes problems.
// [buddy setObject:[self.messageContent objectForKey:#"sender"] forKey:#"jid"];
chatView.buddyData=buddy;
[self.navigationController pushViewController:chatView animated:YES];
[chatView recvdMsg:self.messageDictionary];
}
}
}
To create NSMutableDictionary from NSDictionary you should use dictionaryWithDictionary which is declared in NSDictionary.h.
NSMutableDictionary *aMutDictFromAnotherDictionary = [NSMutableDictionary dictionaryWithDictionary:YOUR_NSDICTIONARY_OBJECT];
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];
}
Im trying to display a ViewController, from my openURL function inside my AppDelegate class, but im not having any luck. Ive tried every solution i could find on the internet, im not sure what im doing wrong... please note i have a tabbed application..
I dont really want to use self.tabBarController.selectedIndex because I really want to display a custom built controller like so:
CategoryTableViewController *controller = nil;
NSUInteger catId = 6;
NSString *title = #"Cat Title!";
NSManagedObjectContext *inMemoryContext = [xyzclient newContextUsingInMemoryStore:YES];
controller = [[CategoryTableViewController alloc] initWithManagedObjectContext:inMemoryContext];
[(CategoryTableViewController *) controller setParentCategory:catId];
[(CategoryTableViewController *) controller setFilterCategory:NO];
[(CategoryTableViewController *) controller setStopRefresh:YES];
controller.title = title;
[self.tabBarController.selectedViewController.navigationController pushViewController:controller animated:YES];
Here is the code ive written:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *scheme = [url scheme];
if ([scheme hasPrefix:#"xyz"]) {
//Attempt 1
UINavigationController *searchNavigationController = [self navigationControllerForViewControllerClass:[SearchTableViewController class]];
[self.tabBarController.selectedViewController.navigationController pushViewController:searchNavigationController animated:YES];
//Attempt 2
NSManagedObjectContext *inMemoryContext = [DealsClient newContextUsingInMemoryStore:YES];
SearchTableViewController *controller = [[SearchTableViewController alloc] initWithManagedObjectContext:inMemoryContext];
[self.tabBarController.selectedViewController.navigationController pushViewController:controller animated:YES];
}
}
- (UINavigationController *)navigationControllerForViewControllerClass:(Class)viewControllerClass {
BaseViewController *viewController = [[viewControllerClass alloc] init];
viewController.context = [self managedObjectContext];
UINib *nib = [UINib nibWithNibName:#"BaseNavigationController" bundle:nil];
UINavigationController *navigationController = [[nib instantiateWithOwner:nil options:nil] lastObject];
navigationController.viewControllers = [NSArray arrayWithObject:viewController];
return navigationController;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[super application:application didFinishLaunchingWithOptions:launchOptions];
self.window.rootViewController = self.tabBarController;
[DClient setBaseManagedObjectContext:[self managedObjectContext]];
UINavigationController *featuredNavigationController = [self navigationControllerForViewControllerClass:[FeaturedTableViewController class]];
featuredNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(#"Home", nil) image:[UIImage imageNamed:#"tabbar_home"] tag:TabBarTabHome];
UINavigationController *browseNavigationController = [self navigationControllerForViewControllerClass:[CategoryTableViewController class]];
browseNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(#"Browse", nil) image:[UIImage imageNamed:#"tabbar_browse"] tag:TabBarTabBrowse];
UINavigationController *searchNavigationController = [self navigationControllerForViewControllerClass:[SearchTableViewController class]];
searchNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(#"Search", nil) image:[UIImage imageNamed:#"tabbar_search"] tag:TabBarTabSearch];
UINavigationController *messagesNavigationController = [self navigationControllerForViewControllerClass:[MessagesTableViewController class]];
messagesNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(#"Messages", nil) image:[UIImage imageNamed:#"tabbar_messages"] tag:TabBarTabMessages];
UINavigationController *cartNavigationController = [self navigationControllerForViewControllerClass:[CartTableViewController class]];
cartNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(#"Cart", nil) image:[UIImage imageNamed:#"tabbar_cart"] tag:TabBarTabCart];
NSArray *viewControllers = [NSArray arrayWithObjects:featuredNavigationController, browseNavigationController, searchNavigationController, messagesNavigationController, cartNavigationController, nil];
[self.tabBarController setViewControllers:viewControllers animated:NO];
[xyzEngine setTabBarController:self.tabBarController];
[self.tabBarController setCartBadgeValue:[xyz numItemsInCart]];
NSLog(#"Loaded the page....");
return YES;
}
Ok I'm still not entirely sure of what you're trying to achieve exactly so I'm gonna assume the following:
You have a tab bar controller with 5 items. Each item is a navigation controller that has a specific class. Based on the url parameter passed to application:openURL:sourceApplication:annotation: you want to select the proper item (which was already been loaded previously in application: didFinishLaunchingWithOptions) of your tab bar controller .
Here's my attempt:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if ([scheme hasPrefix:#"xyz"]) {
Class navigationControllerClass = [SearchTableViewController class];
NSUInteger navigationControllerIndex = [self.tabBarController.viewControllers indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
BOOL found = [obj isKindOfClass:navigationControllerClass];
if (found) {
*stop = YES;
}
return found;
}];
if (NSNotFound != navigationControllerIndex) {
self.tabBarController.selectedIndex = navigationControllerIndex;
}
}
}
Take 2
In your 2 attempts you're creating a new navigation controller and then try to push it on something that's nil (self.tabBarController.selectedViewController.navigationController is nil since self.tabBarController.selectedViewController is a navigation controller).
Whatever you're pushing in your navigation controller cannot be another navigation controller. So you need to create a simple view controller of type UIViewController and push it to the currently selected navigation controller of your tab bar.
if ([scheme hasPrefix:#"xyz"]) {
MYViewController *controller = [[MYViewController alloc] initWithManagedObjectContext:inMemoryContext];
[(UINavigationController *)self.tabBarController.selectedViewController pushViewController:controller animated:YES];
}