I have an iPhone application and I do this in my MyView1Controller:
MyView2Controller *myV2C = [[MyView2Controller alloc] initWithNibName:#"MyView2" bundle:nil];
myV2C.shareObject = self.shareObject;
[self.navigationController pushViewController:myV2C animated:YES];
[myV2C release];
So I push shareObject to the next ViewController. There, in viewDidLoad, I set a property of shareObject like this:
self.shareObject.myText = #"Test String";
So in MyView2Controller, everything is okay, the String is set. But going back to the previous MyView1Controller with the left upper "back" Button, the value of shareObject.myText is not set to Test String.
So, how can I do this? I want to give the View2Controller an object which can be modified, and the modifications I want to have in the View1Controller.
Does anyone know? Thank you in advance & Best Regards, Tim.
OR you can even try using the Singleton pattern
http://www.cocoadev.com/index.pl?SingletonDesignPattern
You can use delegation pattern and/or key value observations
EDIT:
You can achieve this my creating a single object, and then use that object in all classes, wherever you want. For this you can use singleton class, Or you can create a class method. For ex:If I have class A, and I want to push some values in B class, So if I modify the values in B, the newly updated value can be retrieved in a too, or in any other class. In that case, you can create a different class (usually subclass of NSObject),and then write the getter/settor methods in that.
Suppose the name of this newly created class is Manager, then in Manager. m create getter/setter methods, like
NSString *strGlobal;
+(void)setString:(NSString *)strTemp
{
if(!strGlobal)
{
strGlobal = [[NSString alloc] init];
}
//point to same location
strGlobal = strTemp;
}
+(NSString *)getMySavedString
{
return strGlobal;
}
Now In you class A , where you want to send the value to Class B controller, call the setter method to set the value, like: -
-(void)navigateto_ClassB
{
//Setting the value, that should be sent to the other controller
[ManagerClass setString:#"Hello"];
[self.navigationController pushViewController:[[[ClassB alloc]init] autorelease] animated:YES];
}
Now In class B (Or wherever you want to get the saved value, use getter method, like:-
NSString *strSavedValue = [ManagerClass getMySavedString];
No you will have the value, If you want to update the value from anywhere, the again call the setter method, with new value. For ex, i want to update the value in class B, then
[ManagerClass setString:#"Hello Upadted"];
Now this value is updated to same memory location, retrieve it from anywhere using getter method created in Manager class.
As I stated earlier, this is the easiest but not the best approach. Alternatively, you can achieve same functionality with delegate patterns, KVOs (Key value observations) and/or singleton class.
tia was right: "You did it right already, so there must be something wrong somewhere".
It was my fault, so the source code in my question is correct.
Related
I've realized that several of my list view controllers behave in the same way, and now I want to abstract them into a generic one called ListVC. The plan is to create an instance of ListVC when its needed, and pass into it all of the specific things needed for that instance of it.
For example, if I need a list of customers I would do something like:
ListVC *customersVC = [[ListVC alloc] init];
customersVC.tableArray = self.customersList
In ListVC, there are times when I need to know certain object's class type. In my example, the objects in the array self.customersList are from the class CustomerClass. I know I can convert strings to class names but that doesn't help when I have a method inside ListVC that needs to return the object's type. For example, in ListVC, this old non-abstracted method:
- (CustomerClass *)customerAfterFilter
should be something like:
- (self.objectClass *)objectAfterFilter
And I'd set objectClass after it was instantiated like so.
ListVC *customersVC = [[ListVC alloc] init];
customersVC.tableArray = self.customersList
customersVC.objectClass = [CustomerClass class];
How do I do something like this? Or if my approach is just wrong, please suggest the correct approach. I'm a beginner in programming.
You can't change the return type like that. What you can do is return an id, which is a pointer to an object of any class.
- (id)objectAfterFilter
EDIT:
Customer *c = [customersVC objectsAfterFilter];
[c duCustomerStuff];
Alternatively:
[((Customer *)[customersVC objectsAfterFilter]) doCustomerStuff];
I am just curious as if there is anyway to assign a property that is being triggered from class method?
Ex:
+ (void)asyncResponse:(NSDictionary*)response:(NSError*)error
I am getting a response of NSURLConnection in that call, however, I am trying to use this in my another class and set that dictionary as a property, but it gives me the error as this is a class method. That asyncResponse is a "Delegate call" I am using to direct to any particular class in runtime.
Thanks.
There are lot of options you may use to store the variable. Why do you need a property in class method. Class method is run when there is no role of instance. But, of course you, could pass create an instance of the class in the class method and store the value in the object. Other way would be to create some global variables and assign the values to it such that it can be accessed through out the class.
Creating instance to store the variable into property;
+ (void)asyncResponse:(NSDictionary*)response:(NSError*)error{
MyClass *me = [[MyClass alloc] init];
me.someProperty = response;
}
But, I dont think you were looking for this, because it is very simple use of the class and properties.
The other thing you could do is create some static variables inside your implementation and then access those variables through your class. You could even create your own custom getter and setter for it, for more easy uses.
#interface MyClass:NSObject
+(void)setResponse:(NSDictionary*)response;
+(NSDictionary*)response;
#end
NSDictionary *globalResponse;
#implementation MyClass
+(void)setResponse:(NSDictionary*)response{
if(response != globalResponse){
globalResponse = response;
}
}
+(NSDictionary*)response{
return globalResponse;
}
You could set the default value for the response in initialize or load method. This makes a simple class level property.
i have a little question about getting access to a method in another controller, nu i am trying this.
So for example i have the controller A and B. In the controller A i have programmed a method, now i want to get access this through controller B.
What i have done in class A in the header file:
+(void)goBack;
and in the implementation file:
+(void)goBack {
NSLog(#"go back");
}
in the controller B i do this to get access to the method in controller A:
+(void)goPreviousArticle:(id)sender {
ViewProductInformation_ViewController *theInstance = [[ViewProductInformation_ViewController alloc] init];
[theInstance goBack];
}
However when i execute the program, then it does not work, the program just shuts down, when i do command click on the function goBack in controller B i get referred to the method in controller A.
Does anybody have an idea what the problem could be?
thanks in advance,
snowy
It's quite easy ... you just mixed the class and instance-method declaration: The "+" sign indicates that the method is a class method. In your case it should be a "-" so
-(void)goBack; // a instance method declaration!
Hope this helps.
Class vs instance method declaration ... see also What is the difference between class and instance methods?
You are declaring goBack as a CLASS method (with the preceding "+"). Change the + to a -.
Since goBack is a static method of Class A, you don't need an instance of A to call it's method, you can just call it like so:
[ClassA goBack];
You don'y need to declare static functions you can writ like this:
-(void)goBack {
NSLog(#"go back");
}
In the class A and same in the class B:
-(void)goPreviousArticle:(id)sender {
ViewProductInformation_ViewController *theInstance = [[ViewProductInformation_ViewController alloc] init];
[theInstance goBack];
}
Then use them. I think in that case application will not crashed.
What is the difference between class and instance methods in Objective-C and when should I use each of them?
Using the tired old Car analogy...
Think of a Class like it is a factory that makes Instances of the class. For example, you might have a Car class and you might declare a method like:
+ carWithColor: (NSColor *) aColor;
And that method would then create a new Car instance, set the color, and return it:
+ carWithColor: (NSColor *) aColor
{
Car *aCar = [[[self alloc] init] autorelease];
[aCar paintWithColor: aColor];
return aCar;
}
Now, that Car class would then declare an instance method that allows the car to be painted. Why an instance method? Because every car can have a different color (and the color of the car would likely be stored in an instance variable).
- (void) paintWithColor: (NSColor *) aColor
{
... do your paint stuff here ...
}
This is explained in the Objects, Classes, and Messaging section of the Objective-C documentation.
This is an old post, but since it comes up first in a Google search I thought I'd add to it.
I'm not going to talk about class methods used as factory methods. I'd like to talk about their use in utility methods. You can/should use class methods for utility methods that are independent of state. What does this mean? Well, for instance, if you're formatting a date the same way for all instances, that's a utility method that should be a class method. Think of the utility method like a screw driver. You don't need to make a new instance of the screw driver every time you want to do something with it. The screw driver remains constant. So, for instance, I have a class that includes a private method that generates a string of emDashes used for displaying to the view. This method is not dependent on state and hence will not vary by instance. Think of class utility methods like constants.
+ (NSString *)emDashString {
return #" \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014";
}
You can call this method generically within the class (it's private in my example) like this:
NSString *string = [[self class] emDashString ];
I've deliberately chosen a bit of a trivial example to drive the point home. You would only bother making this a class utility method if you're going to need this string more than once in your class. Notice that instead of referring to the class by name I call it generically with [self class] since this is called internally. If it's exposed and you want to call it from another class then refer to it by the class name as usual.
Instance methods do things with instances of a class:
NSString *myString;
myString = [[[NSString alloc] initWithString:#"Hello, world."] autorelease];
NSLog (#"myString's length: %u", [myString length]); // instance method
Class methods can do class-specific things without relying on an object instance, often returning an instance of the class, or some other class-specific result:
NSLog (#"%#", [NSString stringWithString:#"Hello, world."]); // class method
I think it may be rare to see class methods that do not return something.
You don't need to implement both. Either option is available to you as you design your class.
An instance method can operate on an instance of the class. This can get or set a property, or cause behavior you only want that instance to perform. You need to actually have an instance to use it. These can either use or change the state of the instance.
// Notional instance methods
myHouse.color = blueColor;
[myCar accelerate];
speed = myCar.speed;
A class method operates on the notion that the class exists. It can be used to create an instance, or perform a calculation that doesn't depend on having an instance. You might have a class for custom math helper, that essentially contains functions.
// Notional class method uses
myString = [NSString stringWithFormat:#"&f", floatToConvert];
myResult = [MyMathHelper MyFunctionWithInput:myInput];
Class method signatures are prefixed with +, instance methods with - so in your header file declarations would look something like this:
-(void)setAllThings:(NSArray*)things; //instance method
+(void)setAllClassThings:(NSArray*)things; //class method
And of course the same rules apply when you define the methods in the .m file.
Example:
I have 10 view controllers, which are all allocated and initialized in the same way:
UIViewController *controller = [[MyViewController alloc] initWithNib];
(note that -initWithNib is a custom method of a UIViewController subclass)
The next view controller class is OtherViewController, and so on. I want to load the view controllers lazily, just when I need them. But to do that, I need to have some kind of "array" that will give me the corresponding class for a given index, so that I can initialize it.
I ended up creating a method with a big switch-statement, that will just do that nasty allocation and initialization separately for every single view controller. I'm not happy with that. There it would be much better if I could assign the appropriate class to a variable, and then at the end of the switch statement just allocate and initialize that class from the variable.
Is there a way to achieve that?
EDIT: I've found a function
id class_createInstance(Class cls, size_t extraBytes)
and every class seems to have a property "class". But I can't assign it to an instance variable. This doesn't work:
Class cls = [UIImage class];
cls *image = [cls imageNamed:#"avatar.png"];
The first line compiles. But the second one gives an error: "image undeclared".
If you know the names of the classes at compile time, you can assign the classes to Class variables. For example:
static Class factory[2];
factory[0] = [MyViewController1 class];
factory[1] = [MyViewController2 class];
...
Then you could have (classid would be a constant known at compile time that would map to a desired class:
-(UIViewController*)createViewController:(int)classid
{
return [[factory[classid] alloc] init];
}
Assuming that method is defined in a class named MyFactory, you can then do:
MyFactory * fac = [[MyFactory alloc] init];
UIViewController * v1 = [fac createViewController: 0]; // typed
id v2 = [fac createViewController: 1]; // untyped
If you don't have the compile time name of the class, you can simply do the following:
#include <objc/objc-runtime.h>
id object = [[NSClassFromString(#"TheClassName") alloc] init];
Since your original question involves a set of UIViewControllers though, there's no reason to lose type safety with the latter method.
You want to use reflection:
id controller = class_createInstance(NSClassFromString(#"your class name"), 0/*extra bytes*/);
Objective-C Runtime Reference
I blogged about this last month at:
http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html
Essentially, it involves a new class I call the ClassConstructor, which takes a class name, init method name, and comma separated arguments. When you need to create an instance of that class, just use your [myClassConstructor create];
What you want is Reflection. No idea of objective-c has it though - but the term might help you Google for your answer better.
The Objective C Reference also will be a good place to look to get the calls. Try searching for Objective-C 2.0 Runtime Reference since I cant add links