Access another classes properties, returning 0 - objective-c

still having problems!
I have 2 classes, and i want to access the properties of one class from the other.
I have a class called MenuViewController, which is a Facebook styled popout menu, and depending on which cell is selected, i want to load different data.
I have created a property:
#property int rowSelected;
and synthesized it:
#synthesize rowSelected;
and in my other class, i have created an instance of the class:
MenuViewController *menu = [[MenuViewController alloc] init];
NSInteger rowValue = menu.rowSelected;
and when i NSLog it, it always returns 0...
NSLog(#"%i", menu.rowSelected);
Help is much appreciated!

The call to alloc creates a new MenuViewController instance. Unless you set a value for your property in its init method, then you should expect it to be 0.

Related

Using an allocated and initialised object outside of viewDidLoad?

I hope the question title is adequate
Just confused about something in a piece of code I have seen in an online tutorial. There is a generic ZHEDog class with declared properties, methods, etc. and from this class we have created several instances - firstDog, secondDog, fourthDog, and so on.
Now, when we created each instance we did so inside of the viewDidLoad method of our main(one)view controller with the line:
ZHEDog *fourthDog = [[ZHEDog alloc] init];
and then we set some of its properties like name, and so on, here after this line.
So we did this instance creation in the view controller's viewDidLoad and so far have not subclassed the generic ZHEDog class, so it is all deriving from the one class file.
Now, where I am confused is that apparently I cannot set a property of this instance in another method (other than viewDidLoad), so I can't say something like:
-(void) printHelloWorld
{
fourthDog.name = "something new";
}
It kind of makes sense but I can't explain why. I would have thought once the instance was allocated and initialised I could change its properties where I wanted to if necessary? But do the same rules of scope apply to viewDidLoad?
Use properties, they are like instance variables accessible from everywhere within the instance of the class
#property ZHEDog *firstDog, *fourthDog;
then instantiate them in viewDidLoad
self.firstDog = [[ZHEDog alloc] init];
self.fourthDog = [[ZHEDog alloc] init];
and change them in a method
-(void) printHelloWorld
{
self.firstDog.name = "woof";
self.fourthDog.name = "something new";
}
What #vadian has is correct, but using properties also allows other classes to see this variable. Say if you imported the header file and it contained #property ZHEDog *firstDog, *fourthDog;. These variables become public. unless they're in the implantation file.
But other approach is creating variables like so:
Header File
#interface ViewController : UIViewController {
ZHEDog *firstDog, *fourthDog;
}
#end
All will be the same expect now the values are private, or exclusive, to just the ViewController. therefore not allowing others to use or see these variables. And to access the variables in your function printHelloWorld:
- (void)printHelloWorld {
firstDog.name = #"woof";
fourthDog.name = #"something new";
}
Allocating
- (void)viewDidLoad {
//new is the combination of alloc and init. only use +new when using alloc and init, not alloc and initWith...
firstDog = [ZHEDog new];
fourthDog = [ZHEDog new];
}
i hope this would better your goal :)

How can I use a string variable in place of a class name when alloc'ing it

My app has a large number of view controllers declared in the interface for example:
ViewController_1_0 *viewController_1_0
ViewController_1_1 *viewController_1_1
ViewController_1_2 *viewController_1_2
etc ...
(I realize the underscores are not a good Cocoa coding convention for class names and will change that.)
My intent is to present appropriate controller views based on the current UIStepper value.
Rather than do conditional tests for each of the stepper values and then perform a separate lazy instantiation of the controller object using the "hard coded" view controllers I am trying to have code appearing once using strings constructed based upon the current stepper value.
I've figured out (with help from Use a Class name stored in a variable to call a Class method?) how to set up the Class name: I've declared a property:
#property(strong, nonatomic) Class classStringClass;
And then after constructing the variable string for the class, I do:
classStringClass = NSClassFromString(classString);
Where classString is the constructed string using the stepper value, equivalent to ViewController_1_0, for example.
I've also declared a property for the ivar as:
#property (strong, nonatomic) NSString *classInstanceString;
Therefore I do:
if(!classInstanceString) {
classInstanceString = [[classStringClass alloc] initWithNibName:classString bundle:nil];
}
Where I am stuck is how to code for the ivar for the controllers, i.e., classInstanceString constructed to be the equivalent of the ivar viewController_1_0 (or whatever based on the stepper value) declared in the interface. Once I get out of the lazy instantiation if statement and then code to access properties of classInstanceString, for example:
classInstanceString.view.hidden = NO;
classInstanceString understandably gets an error "Property 'view' not found on object of type 'NSString'".
How do I declare 'classInstanceString' (or another variable, say 'classInstanceVariable' containing the classInstanceString value) so when instantiating it, it is the ivar of classStringClass and has access to the class properties, to use subsequent to the instantiation of the class ? I surmise that it should be a different type than an NSString, but what type would that be, or is there another way to do this ?
If you just need basic UIViewController ivars you could always cast it to a UIViewController.
UIViewController *vc = (UIViewController *)[[classStringClass alloc] initWithNibName:classString bundle:nil];
[vc view];// works!
Or if you need custom ivars it would be a good idea if they all extended a base class (or protocol) like so:
MyBaseViewController *vc = (MyBaseViewController *)[[classStringClass alloc] initWithNibName:classString bundle:nil];
[vc customVar]; //works

Load custom class properly

I have a custom class which I want to "load" inside the firstViewController and then access it from other classes by segues. My Problem is, I can't even access and change the instance variable inside the firstViewController. Somehow I'm "loading" it wrong. Here is the code I used until now:
inside viewController.h
#property (strong, nonatomic) myClass *newClass;
inside viewController.m
#synthesize newClass;
I then try to access it by:
self.newClass.string = #"myString";
if(newClass.string == #"myString"){
NSLog(#"didn't work");
}
Well, I get "didn't work". Why is that?
When I write
myClass *newClass = [myClass new];
It does work. But the class and its properties gets overwritten every time the ViewController loads again.
What would you recommend? Thank you very much.
Like Kaan said, you forgot to initialize your class, You have only declared and created a pointer for it but not the actual object, on your ViewDidLoad add
self.newClass = [[myClass alloc] init];
It does work. But the class and its properties gets overwritten every
time the ViewController loads again.
That's because every time that specific Viewcontroller loads you are reinitializing the class.
If you want a persistent class through all your program look for the singleton pattern.
This is used in the case when you want to have only 1 instance of a certain object, if you try to initialize another instance of that object you will just receive the one you already have.
PD: newClass.string == #"myString" is wrong.
Use the isEqualToString method when comparing strings.

Unable to reference properties from one view in another view

This is the code from the class within which I am trying to reference the properties from the other class(BIDDoubleComponentPickerViewController):
BIDDoubleComponentPickerViewController *dummyObject = [BIDDoubleComponentPickerViewController new];
NSString *selectedValue = [dummyObject value];
NSString *selectedSuit = [dummyObject suit];
However, whenever I attempt to access the variables selectedValue and selectedSuit, they claim that they are null, when I know for a fact that value and suit are not null within the other class. Here is the code that sets the properties in BIDDoubleComponentPickerViewController:
NSInteger valueRow = [doublePicker selectedRowInComponent:
kValueComponent];
NSInteger suitRow = [doublePicker selectedRowInComponent:
kSuitComponent];
value=[[NSString alloc]initWithString:[values objectAtIndex:valueRow]];
suit=[[NSString alloc]initWithString:[suits objectAtIndex:suitRow]];
Here is the code for the declaration of the properties:
#property (strong, nonatomic) NSString *value;
#property (strong, nonatomic) NSString *suit;
Anyone have any ideas?
When you create a new view controller, it doesn't load its view immediately. So if the code where you initialize value and suit is located in the init method, then doublePicker is still nil. Otherwise, if that code is located in viewDidLoad or loadView, then it is still not executed when you try to access value and suit using [dummyObject value]; and [dummyObject suit];
Edit: (After OP's comment)
My answer is still correct because in the line:
BIDDoubleComponentPickerViewController *dummyObject = [BIDDoubleComponentPickerViewController new];
you create a new object dummyObject that is different from the view controller where the picker view was visible. So the values value and suit that you are looking for are properties of the other view controller and not the one you just initialized.
To solve your problem, you should not create a new instance of BIDDoubleComponentPickerViewController but retrieve the instance that holds the values you are looking for.

Add object to NSMutableArray from other class

I have a view controller class called PresidentsViewController that sets up data in a UITableView. This data is in the form of NSMutableArray called list. I have another class, PresidentAddController, that is supposed to handle adding an object of type President to this list based on user inputted data about a president. However, I can't get the object to add to the list. I have confirmed that the user inputted data for a new president is being collected correctly, so it is adding to the list that's in another class that's causing problems. I believe the correct code to add an object to the list is:
[pvc.list addObject:newPresident];
However, I don't know how to properly create the reference/instance/? (which is what pvc would be) to PresidentsViewController inside of PresidentAddController so that I can properly add a new president to the list. I am not using Interface Builder for this because it is just a UITableView.
How do I add a president to the list in this situation?
Edit: Here is how the array is being initialized:
#property (nonatomic, retain) NSMutableArray *list;
And here is how PresidentAddController is being set up in PresidentsViewController:
PresidentAddController *childController = [[PresidentAddController alloc] initWithStyle:UITableViewStyleGrouped];
childController.title = #"Add President";
[self.navigationController pushViewController:childController animated:YES];
[childController release];
Add a pointer to PresidentAddController this way:
// in #interface
PresidentsViewController *listController;
#property (nonatomic, assign) PresidentsViewController *listController;
// in #implementation
#synthesize listController;
Then when you instantiate your PresidentAddController, set the pointer:
PresidentAddController *childController =
[[PresidentAddController alloc]
initWithStyle:UITableViewStyleGrouped];
childController.title = #"Add President";
childController.listController = self;
[self.navigationController pushViewController:childController animated:YES];
[childController release];
So then you can go [listController.list addObject:newPresident]; in PresidentAddController.
EDIT: childController.listController = self calls [childController setListController:self], which in turn reads the #synthesized method in your implementation and sets the pointer *listController to point to the current class (if you're writing code in the PresidentsViewController class, then self is going to be the current instance of PresidentsViewController).
The reason why I use assign is because if you were to use retain, then when you set listController to self it will actually keep an owning reference to the object. This can cause all sorts of problems if you ever try to deallocate PresidentsViewController, because if you have an owning reference in PresidentAddController then it will not deallocate until that reference is also released. Using assign ensures that if you ever release the PresidentsViewController before PresidentAddController disappears, it will be properly deallocated. Of course, maybe you want to keep it around in that situation, in which case using retain here is also fine.
My suspicion here would be that you have a property defined as #property (nonatomic,copy) NSMutableArray *list; Are you getting and exception trying to add the object into the array? If so, it's likely because the copy modifier is returning an immutable copy of the array. Try to create a method that takes the object and adds it to the list without using self.list ... just [list addObject] and if that works then this is your problem.