I have a class "ClassA" with "MethodA", i have also a "ClassB" and I want to call "methodA" from "ClassB"; I write
#classA;
#property(nonatomic, retain) ClassA *classA;
//and also #synthesize...
then I call method with
[self.classA method];
but it don't call the method....then I write in viewdidload in classB
self.classA = [[ClassA alloc]init];
but this thing reset varaibles in ClassA.
How can I solve this situation?
EDIT: I have decided to rewrite my answer as I don't think the original was well worded.
I think you are failing to understand what the Objective-C 2.0 dot notation does. It is confusing, especially if you program in C or C++, as it's syntactically equivalent to the struct field or class variable access operator, but semantically different.
When you use:
self.classA = newClassA;
You are actually doing the same as:
[self setClassA: newClassA];
And when the #property classA is defined with the retain attribute, the compiler generates the setter method as something like:
- (void) setClassA:(ClassA *)newClassA
{
if (classA != newClassA)
{
[newClassA retain];
[classA release];
classA = newClassA;
}
}
In the code you have given:
[self.classA method];
Actually expands to:
[self setClassA: method];
Which is not what you intended.
The simplest way to avoid this confusion is to not use dot notation at all, and especially not within an instance method of the same class that deals with allocation or deallocation of the variable.
You are creating a new instance of ClassA with the alloc and init. You need to set the property to your existing instance of classA, it is difficult to advise how without more context, but perhaps when you are creating class b, do
classB.classA = self;
This assumes that class A creates class B in the first place.
Related
#interface hello:SKScene
#end
#implementation hello
+(void)method{
[self here];
}
#end
main.m
[hello method];
here,when i call this class method without allocating memory for object then method self,belong to whom????
my question is self belong to class that contain the method calling on then because i did not define object then ,why i still can use self on this?????
is it still belong to class on which it calling ??please give me proper concept of self on instance method and class method.
When you refer to self in class method, self refers to the class, itself, not to a particular instance of that class. By using self rather than the actual class name in these class methods, it makes it easier to subclass the class in question. Specifically, the class method will be inherited, but the self references will now refer to the subclass rather than the base class. If you refered to the base class by name, this would not be true.
Consider this factory method:
#implementation BaseClassObject
// THIS IS WRONG
+ (BaseClassObject *)object {
return [[BaseClassObject alloc] init];
}
#end
And consider this subclass:
#interface SubClassObject : BaseClassObject
#end
Then consider code that does:
SubClassObject *object = [SubClassObject object]; // WRONG
The problem is that the object factory method will return a BaseClassObject rather than a SubClassObject. But that is remedied if we alter the definition of that factory class method to use self:
#implementation BaseClassObject
// THIS IS RIGHT
+ (instancetype)object {
return [[self alloc] init];
}
#end
Now when I refer to [SubClassObject object], I'll get an instance of SubClassObject rather than BaseClassObject.
Note: In my contrived example, it's rather important to use self. You may, though, encounter code where it does not appear to be immediately relevant (for example, you might have a base class, but no subclass at this time).
Even in this case, you probably should be in the habit of using self in these class methods, regardless, to "future-proof" your code, so that if you ever subclass this base class at some unforeseen date in the future, these class methods are more likely to function properly even when subclassed.
Just to add a little to Rob's answer: the class object is created automatically by the compiler and/or Objective-C runtime. (It doesn't matter to you which it is.) For all intents and purposes, it's permanent. There's no need for it to be managed.
I always see people debating whether or not to use a property's setter in the -init method. My problem is how to create a default value in a subclass for an inherited property. Say we have a class called NSLawyer -- a framework class, that I can't change -- with an interface that looks like this:
#interface NSLawyer : NSObject {
#private
NSUInteger _numberOfClients;
}
#property (nonatomic, assign) NSUInteger numberOfClients;
#end
And an implementation that looks like this:
#implementation NSLawyer
- (instancetype)init
{
self = [super init];
if (self) {
_numberOfClients = 0;
}
return self;
}
#end
Now let's say I want to extend NSLawyer. My subclass will be called SeniorPartner. And since a senior partner should have lots of clients, when SeniorPartner gets initialized, I don't want the instance to start with 0; I want it to have 10. Here's SeniorPartner.m:
#implementation SeniorPartner
- (instancetype)init
{
self = [super init];
if (self) {
// Attempting to set the ivar directly will result in the compiler saying,
// "Instance variable _numberOfClients is private."
// _numberOfClients = 10; <- Can't do this.
// Thus, the only way to set it is with the mutator:
self.numberOfClients = 10;
// Or: [self setNumberOfClients:10];
}
return self;
}
#end
So what's a Objective-C newcomer to do? Well, I mean, there's only one thing I can do, and that's set the property. Unless there's something I'm missing. Any ideas, suggestions, tips, or tricks?
You should do exactly has you have; call the accessor. The declaring class typically avoids calling its own accessors in init to avoid accidentally calling an overridden accessor in a subclass that might rely on the consistency of data you haven't initialized yet. Your superclass on the other hand should be completely consistent by the time the subclass's init is run, so there is no problem using superclass accessors at that time.
Consider the common and general case: you want to set your transform in a UIView subclass. How would you solve that other than call setTransform:? Subclassing non-Apple code is no different.
Make it #protected. It is very rare to make an ivar or property private these days. Private ivars and/or properties are better declared in the implementation. For that matter #protected ivars/properties are rarely seen in Objective-C but perfectly fine.
Using a setter either as a method or with dot notation is just wrong (yes it works but is really bad form), if you want use setters/getters declare a property.
Clarification: the question is not about mutable vs immutable but about a call to super creating an instance of the correct class. I hadn't thought of using [[self class] alloc] in the base class, and this seems to solve my issues. I'll accept that anser in the next few hours if nothing better comes up :)
The Apple spec says:
If a subclass inherits NSMutableCopying from its superclass and declares
additional instance variables, the subclass has to override mutableCopyWithZone:
to properly handle its own instance variables, invoking the superclass’s
implementation first.
That's very confusing. Consider
#interface Base : NSObject<NSMutableCopying>
#property (nonatomic, assign) NSInteger value ;
#end
#implementation Base
...
#end
#interface Derived : Base<NSMutableCopying>
#property (nonatomic, assign) NSInteger value2 ;
#end
#implementation Derived
- (id) mutableCopyWithZone: (NSZone *) zone {
// Huh ???
Derived * derived = [super mutableCopyWithZone: zone] ;
...
// Huh ??????
derived.value2 = self.value2 ;
return derived ;
}
...
#end
I just do not understand how this code could possibly be correct if I follow the spec.
When the call to [super mutableCopyWithZone: zone] returns, I am expecting that the base class has only allocated enough room for its own ivars. There's no way it can tell that Derived instances need more room for its own ivars.
What is it that the documentation means, really? How should I implement this?
super only changes the way of dispatching (static instead of dynamic). But it does not change the receiver, esp. it does no upcast. In -mutableCopyWithZone: (super) self still points to an instance object of the derived class.
Trouble is possible, if the super method (or super super method and so on) does not implement the object creation in a proper way:
copy = [[BaseClass alloc] init]; // Wrong, an instance of the base class is created
copy = [[[self class] alloc] init]; // Correct, an instance of [self class] == DerivedClass is created
Using the second approach you get an instance of the derived class with full memory for its ivars.
Conclusion: Implement it in this way, if BaseClass implements its -mutableCopyWithZone: properly. Otherwise you have no other change then creating your own copy and init it.
In my books I always write, that there are little reason to use the class name inside a class. Using [self class] (in an instance method) and self (in a class method) are in 99 % the better approaches.
Example iVar foo,
#property (nonatomic) NSString* foo; // inside .h
Option 1
#Synthesize foo; //Inside .m
foo = [[NSString alloc] init]; // viewDidLoad method
Option 2
#Synthesize foo; //Inside .m
self.foo = [[NSString alloc] init]; // viewDidLoad method
Option 3
#Synthesize foo = _foo; //Inside .m
_foo = [[NSString alloc] init]; // viewDidLoad method
Why?
At so many places I have seen code which has different ways of doing init an Object in Obj - C but which one is the best practise?
In this regard, ARC is the same as MRC.
you have specified all these take place in viewDidLoad. in that case, use the setter (Option 2).
if you were to initialize/set in the initializer, then you would use direct access. the basic reason is that in the initializer (e.g. -init), you have a partially initialized object. during initialization, you want to focus on initializing variables your class needs or expects in order to function correctly. as well, you want to avoid side-effects you can encounter when using the accessors in partially constructed states.
in a fully constructed state (e.g. viewDidLoad), you should relegate the implementation to the accessors for correct behavior, as specified by your object's interface.
Additional Reading:
Initializing a property, dot notation
Should I refer to self.property in the init method with ARC?
Why would you use an ivar?
I think you should understand the difference between these three and then decide which one is good for you.
option 1: Here while initializing you are not using the synthesizer method. so there is no use of declaring property-synthesizer in .h and .m
option 2: here you are using property-synthesizer. But the name of the method for accessing the instance and actual instance variable is same.
option 3: Here again you are not using the property-synthesizer method. Here foo is the name of the method and _foo is the actual instance.
In my opinion third one is the good. Since you the difference you can decide which one is good for you.
I want to fire some code when a property is accessed and changed. I use #property and #synthesize in my code for my ivars. The properties are retained, so I'd like to keep that memory management stuff automatically generated by #synthesize.
However, I assume that #synthesize tells the compiler to generate the accessor methods code right where #synthesize is, so most of the cases at the top of the code, right?
And when I have a property foo, I get -setFoo and -foo methods. Could I then just make a method like this, to execute some more custom code when a property is changed?
-(void)setFoo {
// custom stuff
}
Now that's a problem. How to execute the first one? I wouldn't love to have a different name here. Is there maybe a way to let the #synthesize directive create other names for getter and setter methods, which I then call easily? And I would still be able to use the dot syntax then to access them?
You can use #property and #synthesize just like you normally would, but provide a custom setter or getter (or both) and those will be used instead. Typically I will do something like this:
// Override the setter
- (void)setName:(NSString *)aName
{
if (name == aName)
return;
[name release];
name = [aName retain];
//custom code here
}
When I use the set property, it will invoke my custom method. However, the get will still be synthesized.
If you provide an implemnetation for the setters or getters it will use that instead of the generated implementation. Its not hard to implement the "retaining" aspect of the getters and setters that are generated for you by the compiler when u synthesize, so you can just write your own getters and setters i would say and go with that.
One wacky solution is to create an abstract super class that does gives you the normal property synthesis.
Then create a concrete subclass that you will actually use, and that simply implements and override method (same signature) and calls super to do the actual setting.
This allows you to do whatever you want to do before or after the call to super's implementation.
Example:
#interface ALTOClassA : NSObject
#property NSString *catName;
#end
Nothing else needed in the .m beyond the stubbed file for this test.
Create the subclass, nothing needed specially in the #interface
#import "ALTOClassA.h"
#interface ALTOClassAJunior : ALTOClassA
#end
In the #implementation we do our override.
#import "ALTOClassAJunior.h"
#implementation ALTOClassAJunior
- (void)setCatName:(NSString*)aCatName {
NSLog(#"%#",NSStringFromSelector(_cmd));
[super setCatName:aCatName];
NSLog(#"after super: self.catName %#", self.catName);
}
#end
In use:
ALTOClassAJunior *aCAJ = [ALTOClassAJunior new];
NSLog(#"aCAS.catName %#", aCAJ.catName);
NSLog(#"set it to George.");
[aCAJ setCatName:#"George"];
NSLog(#"aCAS.catName %#", aCAJ.catName);
This allows you to leverage the autogenerated code, and still do stuff you want to do with your class. Abstract Super Class is often a useful solution for many things.
Yes, in your #property declaration, you can specify the getter and setter methods.
#property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo;
In your foo and setFoo: methods, call [self privateGetFoo] or [self privateSetFoo:f] then your custom code.
The object can also set an observer on itself with addObserver:forKeyPath:options:context:.
That said, I don't think either of these are very clean ways to do things. Better to write your own getter/setter as others have suggested.