sharedApplication value is not visible - objective-c

Well I have those 2 variables, an NSString and an NSMutable Array which is value I want to be global in all my tabs. So far I had only one (the NSString) and I could get its value normally. No that I tried having one more variable I get (null) value.
here is my code:
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic,retain) NSString *myDate;
#property (nonatomic,copy) NSMutableArray *tracks_condition;
#end
and in the HomeView.m when i assign the values
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
parsed_date=[res objectForKey:#"date"];
NSLog(#"Date:%#",parsed_date);
delegate.myDate = parsed_date;
NSString *parsed_track=[res objectForKey:#"Data1"];
[delegate.tracks_condition addObject:parsed_track];
NSLog(#"Track 0 Static:%#",parsed_track);
NSLog(#"Track 0:%#",[delegate.tracks_condition objectAtIndex:0]);
parsed_date is being printed out normally and I can access it in aother tabs.
But I get:
Track 0 Static:0
Track 0: (null)
And i cannot understand why, as I add it as an object in the MutableArray. Of course i get (null) in every other tab.
Can you help me? i prefer by fixing that code and not suggesting something entirely different because I am not very experienced in IOS. Unless it is that easy.

Most likely this is because you are never instantiating a mutable array for your tracks_condition property. Just declaring a property on your AppDelegate class doesn't create the object for you. You still need to alloc/init the object at some point before you can use it. Until then tracks_condition remains null, and any messages sent to it (such as attempting to add an object to the array) will be ignored.
You can fix this by instantiating an object and setting the value of your property before using it. You could do this in your app delegate's application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.tracks_condition = [[NSMutableArray alloc] init];
}

Related

Instance method returns correct array from one view controller but null from others

This is my first post so apologies for any errors I make, but this has been frustrating me for hours now and I cannot find a solution.
I have an app that uses a UITabBarViewController that has 3 tabs: FirstViewController, SecondViewController and ThirdViewController.
I have an NSObject class (Manager) where I reach out to from my view controllers to pull information from the calendar. Which works perfectly fine when I use the FirstViewController, however, when I go to use the other view controllers it simply returns "null" but I know the instance method is being called because I put an NSLog in the instance method it returns a value, but this value isn't being passed onto view controllers two and three.
The code I am using is below.
AppDelegate.m
#import <UIKit/UIKit.h>
#import "EventManager.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) EventManager *eventManager;
#end
AppDelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.eventManager = [[EventManager alloc] init];
}
EventManager.h
#import <Foundation/Foundation.h>
#import <EventKit/EKEventStore.h>
#interface EventManager : NSObject
#property (nonatomic, strong) EKEventStore *eventStore;
-(NSMutableArray *) fetchCalendars;
#end
EventManager.m
-(NSMutableArray *) fetchCalendars {
NSArray *EKCalendars = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
NSMutableArray *mutableCalendars = [[NSMutableArray alloc] initWithArray:EKCalendars];
NSLog(#"EKCalendars %#",EKCalendars);
return mutableCalendars;
}
FirstViewController.m
-(void)loadCalendars{
NSMutableArray *mutableCalendars = [self.appDelegate.eventManager fetchCalendars];
}
This works absolutely fine for loading the calendars.
SecondViewController.m
-(void)loadCalendars{
NSMutableArray *mutableCalendars = [self.appDelegate.eventManager fetchCalendars];
}
This returns null, however, the output from the NSLog[ NSLog(#"EKCalendars %#",EKCalendars)] gives the exact same output as when it code is ran for the First View Controller.
I can get the calendars from the altering the SecondViewController.m to read
-(void)loadCalendars{
EventManager *per= [[EventManager alloc]init];
calendarsArray = [per fetchCalendars];
}
But I just don't understand why I need to reinitialize the event manager as it is initialized in the applicationDidBecomeActive.
Thanks for any help you guy can give.
You can access the Application's AppDelegate using [UIApplication sharedApplication].delegate:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSMutableArray *mutableCalendars = [appDelegate.eventManager fetchCalendars];

passing data between tabs in iOS

it is my first app that I am trying to do on my own and I have some questions. I want to have 4 tabs, and in the first one named "HomeView" I am parsing JSON data (this is done so far).
But what I want is some of the data that are being parsed to be visible in other tabs (and not have to parse them again).
So parts of my code of HomeView is here:
#import "HomeView.h"
#interface HomeView ()
#end
#implementation HomeView
//other code
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//data fetched
parsed_date=[res objectForKey:#"date"];
NSLog(#"Date:%#",parsed_date);
[UIAppDelegate.myArray addObject:parsed_date];
}
and I can see the "parsed_date" being printed out correctly.
So I want this parsed_date to be visible in OtherView.
This is my code but I cannot print it out.
OtherView.m
#import "OtherView.h"
#import "HomeView.h"
#import "AppDelegate.h"
#interface OtherView ()
#end
#implementation OtherView
#synthesize tracks_date;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//preview value of other class
tracks_date = [UIAppDelegate.myArray objectAtIndex:0];
NSLog(#"Dated previed in OtherView: %#", tracks_date);
}
and (null) is being printed out.
added code of app delegate.h
#import <UIKit/UIKit.h>
#define UIAppDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) NSArray *myArray;
#end
So can you suggest me a sollution?
Add the property to your Application Delegate instead.
When assigning the property do something like:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.myProperty = #"My Value";
then, in your different tabs, you can retrieve this property in the same manner:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *valueInTab = delegate.myProperty;
Uh, when you create a HomeView in your last code segment there, you're creating a new object -- a new instance of the class. It will not contain the data from connectionDidFinishLoading unless that method is executed in that instance of the class.
You basically need to use some sort of persistence mechanism to do what you want, either the AppDelegate or static storage along the lines of a "singleton".
While this may not be the best method of doing this, it is easy and effective.
Save your data in your app delegate and retrieve it from there. You can create a shortcut to your app delegate shared application. Then just access the values there.
AppDelegate.h
#define UIAppDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)
#property (nonatomic, strong) NSArray *myArray;
TabView1.m
#import "AppDelegate.h"
SomeObject *myObject = [UIAppDelegate.myArray objectAtIndex:0];
Like I said, it might not be the best way to organize your data for your application, this method does work for small amounts of data needing to be shared at the application level. Hope this helps.
this happens because you create an instance of HomeView yourself.
it has simply no connections to anything.
your first example works because it is the created and initialized from your nib.
i think the best way is to use an IBOutlet and then connect both 'Views' in InterfaceBuilder.
#interface OtherView ()
IBOutlet HomeView *homeView;
#end
#implementation OtherView
#synthesize tracks_date;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Dated previed in OtherView: %#", homeView.parsed_date);
}
- (void)dealloc:
{
[homeView release];
}
have a look here, it will demonstrate it much more
In InterfaceBuilder you can manage your Objects and connect them (via IBOutlets and IBAction, ...) together.
I think this video is a good demonstration how this concept work.

textView not getting set from another view controller (using Singleton class)

I have a textViewController class. I want to set(basically update) the corresponding textView's content from another view controller which I am pushing over the present textViewController. The way I thought I could do this was to have a shared singleton class and have a string property there to contain the text. I have been using the singleton for storing some other content as well and it worked fine till now.
But the text variable in singleton class doesn't hold the content I pass to it from the second view controller and hence the textViewController, after popping the second view controller, displays the old text even after reappearing. I am updating the textView in its viewWillAppear method which is getting called but shows old text content on NSLogging.
What am I missing here? Please suggest a solution, stuck at it for a long time now.
Declaration
Firstly, declare the NSString in your app delegate .h file. It should look something like this:
//YourAppDelegate.h
#import <UIKit/UIKit.h>
#interface YourAppDelegate : NSObject < UIApplicationDelegate >
{
NSString *sharedString; //WE ADDED THIS
}
#property (nonatomic, retain) NSString *sharedString; //AND THIS
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SomeViewController *viewController;
#end
Now you want to synthesize the object so that the accessor and mutator methods are made for you. This means you don't have to write the setSharedString: and getSharedString methods - we can simply access and mutate the object by making a reference to it. This is how we synthesize it in the .m file:
//YourAppDelegate.m
#synthesize sharedString;
Assigning a Value
When you want to assign a value to sharedString from another class, you must first retrieve the active instance of your application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
The appDelegate object here is your running app delegate instance. To access the sharedString NSString object in the delegate and assign a value, we'd do this:
appDelegate.sharedString = #"some string we want to assign";
For the duration of our application's runtime, "some string we want to assign" is now stored in sharedString in our app delegate.
Retrieving the Value
You'll want to retrieve the value at some point. To do this, again we'll have to get the running instance of our application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
Once we have the running instance, we can then access the sharedString object stored inside it:
NSString *retrievedString = appDelegate.sharedString;
From this point, retrievedString now holds the value "some string we want to assign".
Note:
Everywhere I mention YourAppDelegate, I am referring to your app delegate - the app delegate you have in your project. It'll be related to your project name (look for the file).
How your NSString property for your Text-Variable is defined? Is it a "weak"?

Objective C Adding custom objects into NSMutableArray

I want to store a list of data records in a NSMutableArray for use in a UITableView. In other languages I would have used a simple 'type' structure to define the record structure but I understand the way to do this in Obj-C is to define a new class. I've done this as follows :
#interface CustSuppListItem : NSObject
#property (nonatomic, copy, readwrite) NSString *acCode;
#property (nonatomic, copy, readwrite) NSString *acCompany;
#property (nonatomic, copy, readwrite) NSString *acContact;
#property (nonatomic, assign, readwrite) double osBalBase;
#property (nonatomic, assign, readwrite) unsigned int acAccStatus;
#end
#implementation CustSuppListItem
#synthesize acCode, acCompany, acContact, osBalBase, acAccStatus;
#end
In the viewDidLoad of my UITableViewController I instantiate the array :
tableListDataArray = [[NSMutableArray alloc] init];
Once I have retrieved my data, I add it to the array as follows :
CustSuppListItem *custSuppItem = [[CustSuppListItem alloc] init];
[custSuppItem setAcCode:[jsonCustSuppRecord getStringForKey:#"acCode"]];
[custSuppItem setAcCompany:[jsonCustSuppRecord getStringForKey:#"acCompany"]];
[custSuppItem setAcContact:[jsonCustSuppRecord getStringForKey:#"acContact"]];
[custSuppItem setOsBalBase:[jsonCustSuppRecord getDoubleForKey:#"osBalBase"]];
[custSuppItem setAcAccStatus:[jsonCustSuppRecord getIntForKey:#"acAccStatus"]];
[tableListDataArray addObject:custSuppItem];
[custSuppItem release];
In my table cellForRowAtIndexPath method, I retrieve the data for the current cell as follows:
CustSuppListItem *listDataRecord = [tableListDataArray objectAtIndex:indexPath.row];
[cell.lblCompanyName setText:listDataRecord.acCompany]; // EXC_BAD_ACCESS here
[cell.lblAcCodeContact setText:[NSString stringWithFormat:#"%#, %#",
listDataRecord.acCode, listDataRecord.acContact]];
[cell.lblBalance setText:[Utils fmtNumber:listDataRecord.osBalBase withDecPlaces:2]];
[cell.lblStatus setText:[Utils exchAccStatusDesc:listDataRecord.acAccStatus]];
return cell;
In the dealloc method for the view controller I release the NSMutableArray :
[tableListDataArray release];
I'm very new to Obj-C so it would be great if somebody could confirm everything I've done so far makes sense and is in order. I am getting an intermittent EXC_BAD_ACCESS error when trying to read the acCompany property (see comment next to line) so something must not be right.
Any help appreciated,
Jonathan
All your code looks reasonable and correct to me at first glance.
A few things that I would look at are:
Confirm that cell definitely has a property lblCompanyName. If you're trying to assign to a property that doesn't exist then you will get this type of error. Have you defined a custom cell object type?
Confirm that it is always the acCompany property that is causing the EXC_BAD_ACCESS, and not just any property on the object. One way to do this would be to change the ordering of the lines in the cellForRowAtIndexPath method.
Confirm that the listDataRecord that's causing the crash is getting populated correctly in the first place. In other words, confirm that your jsonCustSuppRecord is always valid. What does jsonCustSuppRecord getStringForKey: return if the key doesn't exist in the jsonCustSuppRecord?
Set a breakpoint at this line: [tableListDataArray addObject:custSuppItem]; and examine the contents of the custSuppItem each time (this is an extension of point 3. above)

Error when using setObject in NSMutableDictionary

I am getting the exception:
-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
The offending line is:
[delegate.sharedData.dictFaves setObject:#"test" forKey:#"4"];
Delegate is initialized thus in MyViewController.m:
delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
This is how my delegate is defined in AppDelegate.h:
#import "CommonData.h"
...
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSString *tempFave;
CommonData *sharedData;
}
#property (strong, nonatomic) NSString *tempFave;
#property (strong, nonatomic) CommonData *sharedData;
sharedData is initialized in AppDelegate.m thus:
#import "AppDelegate.h"
...
#implementation AppDelegate
#synthesize sharedData;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
sharedData = [[CommonData alloc] init];
return YES;
}
sharedData is defined in CommonData.h:
#interface CommonData : NSObject
{
NSMutableDictionary *dictAffirms;
NSMutableDictionary *dictFaves;
}
#property (nonatomic, copy) NSMutableDictionary *dictAffirms;
#property (nonatomic, copy) NSMutableDictionary *dictFaves;
shared data implementation file CommonData.m:
#import "CommonData.h"
...
#implementation CommonData
#synthesize dictAffirms;
#synthesize dictFaves;
#end
I have declared the members of CommonData to be Mutable. Apparently that is insufficient. What else must I do in order to write to the Dictionaries inside CommonData?
I have seen this error before when trying to write to a dictionary that is filled from a plist. If you use
yourMutableDictionary = [someDataSource objectForKey:#"someKey"];
your dictionary will be immutable, even if it is declared mutable. Use instead
yourMutableDictionary = [someDataSource mutableArrayValueForKey:#"someKey"];
and your problem will go away, assuming this is in fact your problem. It might be something like:
yourMutableDictionary = [[NSDictionary alloc] init];
or
yourMutableDictionary = [NSDictionary new];
and you just are accidentally creating immutable objects, which is pretty much the same problem as above, just different.
It would be nice to see the code used to initialize the NSMutableDictionaries.
Edit: Maybe try something like this, as I'm curious as to what the results would be. Instead of using:
[delegate.sharedData.dictFaves setObject:#"test" forKey:#"4"];
try
NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithDictionary:delegate.sharedData.dictFaves];
[dict setObject:#"test" forKey:#"4"];
delegate.sharedData.dictFaves = dict;
[dict release];
You've declared the dictFaves to be mutable, but that doesn't mean you actually stored a mutable object in there. Check your initializer. You'll probably have something like the following:
dictFaves = [[NSDictionary alloc] init];
If so, you need to change that to NSMutableDictionary instead.
Your problem is that your property setter for the dictionary is declared as copy. NSMutableDictionary's copy method returns an immutable NSDictionary (in general, copy almost always returns an immutable object). So assuming you're using the standard synthesized setter, any time you set that property, you're assigning the wrong type behind the scenes. It should probably be strong instead.