load data into uipickerview with NSMutableArray located in app delegate - iphone

basically i have parsed some data from XML into a NSMutableArray that is shared in the appDelegate.
in my secondViewController i have a uiPickerView that i am wanting to load the details of the array into it.
My question is... how?
i have briefly worked with uiPickerView's before and had to load the data in first to assign to the uiPickerView like so:
titleDB = [[NSMutableArray alloc] init];
[titleDB addObject:#"MR"];
[titleDB addObject:#"Mrs"];
[titleDB addObject:#"Ms"];
[titleDB addObject:#"Miss"];
[titleDB addObject:#"DR"];
[titlePickerView selectRow:1 inComponent:0 animated:YES];
but since the data is coming from the appDelegate i don't know how i should load it into the uiPickerview, is it something to do with the datasource?
I'm asking to throw code at me I'm just asking for the best way to do it.
Any help on this would be great
Thanks
Jonn4y

This is a common pattern. You will want to access UIApplication's sharedApplication instance. So assuming your appDelegate class is named YourAppDelegate, the array ivar in YourAppDelegate and viewController is titleDB then you could do this in your viewController's viewDidLoad method
YourAppDelegate *appDelegate=(YourAppDelegate *)[[UIApplication sharedApplication] delegate];
// assuming you are using #property and #synthesize for your ivars
self.titleDB=appDelegate.titleDB;
Good luck

Basically, you want to access the appDelegate object from random places in code. This is not an unusual request. Remember that Objective C is a superset of the C language. And as such, you can use a global variable. What more natural variable would there be in a Cocoa program than the app delegate, for the reasons stated above. So, in your appDelegate .h file, add:
<MyAppDelegateClass> * appDelegate;
Substitute MyAppDelegateClass for the name of your appDelegate class name. Then just include your appDelegate's .h file anywhere you want to use the appDelegate variable, and just use (in your example):
[appDelegate titleDB]
or create a local iVar:
NSMutableArray * titleDB = [appDelegate titleDBData];
Then in your app delegate method didFinishLaunchingWithOptions, add the following line:
appDelegate = self;

Related

Objective-c / xcode - Access button state in different class

So I tried this in many different ways but I can't get it to work. Im trying to change the state of a UIbutton in a different class.
class1.h
#property (strong, nonatomic) IBOutlet UIButton *monthly;
class2.m
- (void)viewDidLoad
{
ViewController *vc = [[ViewController alloc] init];
vc.monthly.enabled = NO;
}
Whatever I try and where ever I put the code, the button state is not changing. When I log the state in class2.m:
NSLog(vc.monthly.enabled ? #"Yes" : #"No");
It always returns No, even if I just stated it as YES in my class2.m. Long story short: My button property is not updating from a different class. Please tell me if you need to see any more code and i'll update asap.
i think problem is with class instance. the following line create new instance
ViewController *vc = [[ViewController alloc] init];
that's why your button state is not changing you have to get reference of your previously created intstace no need to create new instance.
for this you can use AppDelegate file to declare property of class1.
see following code
AppDelegate.h
#Property(nonatomic, ratain) ViewController *vc;
AppDelegate.m
#synthesize vc;
now alloc & initialize vc whenever you need it like following.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication
sharedApplication] delegate];
appDelegate.vc=[[ViewController alloc] init];
also don't forgot to import AppDelegate.h file where you write above code.
now using appDelegate.vc you can use all property of View Controller in all classes of you project.
The main problem is you are creating new instance each time when you are going to check the button state. But the button state is for the button which you have created in class1.h. So you have need that you should create button in Appdelegate class and fetch the instance from Appdelegate in the class where you are checking the status of button and check the status of button. I think it will help.
Access the button using the object of the ViewController class that is already in the stack. No need to creat a new object like ViewController *vc = [[ViewController alloc] init];. When you are doing this it creates a new object so you are not getting the write thing.

how to call a method in iphone applications?

i have a method in delegate.m file
-(void) switchToTabbarController
{
TabBarController *tabBarController =
[[TabBarController alloc] initWithNibName:#"TabBarController" bundle:nil];
[self.window addSubview:tabBarController.view];
}
and i wanted to call this method from my LoginView Method. How to do it?
At first you have to import the header, and then create the object of your Delegate class, and then call the method. It will look like this:
#import "Delegate.h"
In place where you want to call it:
Delegate* del=[[Delegate alloc] init];
[del switchToTabbarController];
And after you are done, I would strongly suggest reading Apple's Objective-C Programming Guide:
Link.
EDIT: if this is your AppDelegate, go with Mats' solution.
First I think you do not want to call it this way. I prefer not to call the UIApplication from a view and try to prevent it from a controller. Use a notification instead.
But the way you could do this is:
[(ApplicationDelegate *)[UIApplication sharedApplication].delegate switchToTabbarController]
include header file -
#include
create instance of this class
delegate *d=[[delegate alloc] init];
[d switchToTabbarController];

iPhone - When to release the application delegate?

I have an object that is used between all my viewControllers so I have stuck it inside the application delegate. (I assume this is the correct place?).
If an action inside a viewController fires that needs to send something to said object I am performing the following:
- (IBAction)sliderMoved:(id) sender{
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[[delegate myObject] setSpeed:(int)slider];
// [delegate release];
}
I am a bit concerned I am not releasing the delegate object anywhere, is this ok? If I remove the commented line [delegate release] it just crashes the application.
You don't own the delegate object that you create in this snippet. You haven't created it with alloc, new, or a copy. Nor have you retained it. So, it is not your responsibility to release it.
As for putting an object in the Application delegate just to be able to access it from other parts of your code - that is poor OOP design IMO.
Edited to add
I suppose I had better give an example
Suppose you have a class MyClass that you want to create an object of that you can pass around.
You create it in the Application delegate, which it seems you are already doing:
MyObject *myObject = [[MyObject alloc] init];
Then you create another view controller - which you would normally do, except that this view controller has a property:
#property(retain) MyObject *object;
And then you set this property when you create the view controller:
YourViewController *vc = [[YourViewController alloc] init];
vc.object = myObject;
And, if you pass this object to other view controllers as you require.

What's the best place to load a NSDictionary you want to be accessible to all views?

I have a tab bar application with 4 different tabs.(4 different views)
When my app first launches, the first thing I need to do is bring in my data which is located in a plist. This isn't a problem. My problem is, the data is displayed in each tab in a different way.
Where do you suggest the best place to load the data is?
Currently I'm using viewDidLoad of the first viewController. But from here, what do you think the best way to make the data available to the other views is? Perhaps make the other 3 views become a delegate for the 1st view?
Any suggestions would be much appreciated
Thanks for you help.
Mike.
I don't know why each of the four views can't have a reference to the dictionary, and your application delegate loads from the plist and set the references. Is your data very large?
The little data I've had that is truly global in this way I've made a property on my AppDelegate class. Your view controllers can all access it with
MyAppDelegate* delegate = [UIApplication sharedApplication].delegate;
id thing = [delegate.myDictionary objectForKey:#"someKey"];
This is an often asked question here. You should look at the MVC design pattern. Your dictionary would be a model in this scenario and all the controllers/views that need to access it should have their own property for it. The loading can be done in another controller/view with a progress bar, in the application delegate or in the first tab; that depends on your situation.
The classes would look a bit like this:
#interface Model : NSObject {…}
- (void) load;
#end
#interface ControllerA : UIViewController {…}
#property(retain) Model *model;
#end
#interface ControllerB : UIViewController {…}
#property(retain) Model *model;
#end
#implementation ApplicationDelegate
- (void) applicationDidFinishLaunchingAndWhateverElseIsUsuallyHere
{
Model *model = [[Model alloc] init];
[model load];
ControllerA *controllerA = [[ControllerA alloc] init…];
[controllerA setModel:model];
ControllerB *controllerB = [[ControllerB alloc] init…];
[controllerB setModel:model];
[model release];
// The syntax here is probably off, you should get the idea
UITabBarController *tabs = …;
[tabs setViewControllers:controllerA, controllerB, nil];
[window addSubview:tabs.view];
[window makeKeyAndVisible];
}
I don't have any experience with Tab Bar views, but it looks like you want to create a singleton class, so that you can access your dictionary globally.

Creation of new Nav views, which one should be the best ? iPhone

I have been wondering which is the best way to load a navigation view. I have found that there are 3 ways I can do it without having major errors
What I was wondering is which one is best for memory and as a recommended practice ??
1)
no declaration in .h file (the code below IS NOT writen in the .h file)
#interface companyViewController : UIViewController {
EmployeeViewController *employeeDetailViewController;
}
#property (nonatomic, retain) EmployeeViewController *employeeDetailViewController;
then no #syntesize in .m file, no release in dealloc and no nil in viewDidUnload and when I call the new view I do:
EmployeeViewController *employeeController = [[EmployeeViewController alloc]
initWithNibName:#"EmployeeViewController" bundle:nil];
[self.navigationController pushViewController:employeeController animated:YES];
[employeeController release];
2)
I create it in the .h file (the code below IS written in the .h file)
#interface companyViewController : UIViewController {
EmployeeViewController *employeeDetailViewController;
}
#property (nonatomic, retain) EmployeeViewController *employeeDetailViewController;
then I #syntesize in .m file, with a release in dealloc and a nil in viewDidUnload and when I call the new view I do:
EmployeeViewController *employeeController = [[EmployeeViewController alloc]
initWithNibName:#"EmployeeViewController" bundle:nil];
employeeDetailViewController = employeeController;
[self.navigationController pushViewController:employeeController animated:YES];
[employeeController release];
3)
I do like 2 but I call the new view like this
employeeDetailViewController = [[EmployeeViewController alloc]
initWithNibName:#"EmployeeViewController" bundle:nil];
[self.navigationController pushViewController:employeeController animated:YES];
I feel like #3 is wrong because from what I understand in the memory management, I allocate it once in the #property (nonatmoic, retain) and I also retain it when I alloc it when I decide to call it. This will make the view have a retain count of 1 and lead to leaks.
To make sure I do not create an excessive amount of new views and get EXC_BAD_ACCESS or memory leaks, which one should be best ?
Thanks for the help
In none of these examples are you actually using the property you declare. I'll go through them in turn.
You created a property called employeeDetailViewController, but you never synthesize it or store anything in it. Your view controller is only ever stored in a local variable before passing it off to the navigation controller.
You create an instance variable called employeeDetailViewController, and a property also called employeeDetailViewController. However, you never store anything in the property, you only access the instance variable directly. Since you don't retain the view controller (it doesn't happen automatically when you use instance variables), you've got a situation where you might over-release.
This one will actually crash. You told it to pushViewController:employeeController without having defined employeeController.
So, let's consider what's right. There are two issues here: firstly, how to use properties, and secondly, whether you need an instance variable/property to refer to the view controller at all.
Considering properties:
To access a property, you use self.propertyName. If you just use propertyName directly, you're writing directly into the instance variable, and the memory management stuff (like automatically retaining stuff that's put in the property) is completely bypassed. Generally, you should only ever do that in your init or dealloc method: everywhere else you should access the property properly by self.propertyName.
Do you need an instance variable/property for the view controller?
I would say you don't actually need an instance variable or property for the view controller you're pushing. Once it's been handed off to the navigation controller, in general you won't need to access it again. My version of your code would be:
aViewController = [[EmployeeViewController alloc]
initWithNibName:#"EmployeeViewController" bundle:nil];
[self.navigationController pushViewController:aViewController animated:YES];
Unless you're wanting to refer to that particular view controller from elsewhere in your code, this is all you need. Nothing in the header, no property anywhere.
Property access is more like
self.employeeDetailViewController = [[[EmployeeViewController alloc] initWithNibName:#"EmployeeViewController" bundle:nil] autorelease];
And then,
-(void)dealloc {
self.employeeDetailViewController = nil;
[super dealloc];
}