mutableCopyWithZone confusing requirement? - objective-c

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.

Related

Pros and cons of using "id" as the return type of a custom "init" method, instead of a pointer to that class?

Assume the following Objective-C class:
#interface Appliance : NSObject
{
NSString *productName;
int voltage;
}
#end
What are the pros and cons of implementing init method A instead of B?
A) -(id)initWithName:(NSString *)name;
B) -(Appliance *)initWithName:(NSString *)name;
I see they both work in XCode, i.e. they both will result in a valid Appliance instance. "A" seems to be the standard among books I've read and codebases I've looked at, and I'm wondering why this is.
Point in fact, for quite some time the best practice return type from a class initializer (in Objective-C) is instancetype instead of id.
Oh, reopen. :-)
Indeed, you did not ask for the difference id vs. instancetype. And for -init… the answer to this non-asked Q would be easy: There is no difference, because the compiler converts id to instancetype silently.
You asked for id vs. CustomClass*. And you get a completely different answer from me: With CustomClass* a subclass had to cast the result of the superclass' designated initializer. Let's have an example:
#interface BaseClass : NSObject
- (BaseClass*)initWithWhatever; // Typed to class, designated initializer
#end
#implementation BaseClass
- (BaseClass*)initWithWhatever // Typed to class
{
self = [super init]; // What's the return type of -init (NSObject)?
…
}
#end
#interface Subclass : BaseClass
// First problem: I like it to announce in the interface, that a class overwrites
// a method of the base class. Doing so I would have to change the return type. Ugly.
// If I do not redeclare -initWithWhatever it is inherited from BaseClass, still
// having BaseClass* as the return type. Is that the truth? Really?
// However, I do not overwrite it here, but have a new initializer.
- (Subclass*)initWithSomethingElse;
#end
#implementation Subclass
- (Subclass*)initWithSomethingElse
{
// Second Problem:
// First, I have to execute the superclass' designated initializer
self = [super initWithWhatever];
// Wait a minute!
// self is a reference to Subclass. The return value of -initWithWhatever has the type
// BaseClass*. So I assign a reference of the base class to a reference of the subclass:
// Compiler error, false positive. The code is correct.
// So I would have to cast. Ugly, ugly, ugly.
#end
…
// Third problem:
Subclass *object = [[Subclass alloc] initWithWhatever];
// Typing -initWithWhatever to BaseClass* would lead to a compiler error here again.
// Compiler error, false positive. The code is correct.
To make the long story short: Without a mass of castings it would be impossible to type initializers to the concrete class.

Passing a class instance as a parameter to one of its own functions

When a class of properties (let's call it class_X) is being instantiated from another class, all of class_X's methods and functions are also included in every instance.
Q1: Wouldn't that add substantial overheads, especially if there are multiple instances of that class?
The class instance (class_X) could then be passed to other methods and functions in other classes as a parameter.
Q2: Is it safe to pass it as a parameter to a C-style function (let's call it function_C) which resides in the same class (function_C resides in class_X)?
Thanks in advance.
UPDATE: Here's some code to illustrate:
class_X header:
//class_X.h
#interface class_X : NSObject
#property (nonatomic, assign) NSInteger intProp;
#property (nonatomic, strong) NSArray *arrProp;
void function_C (class_X *cx);
#end
class_X implementation:
//class_X.m
#import "class_X.h"
#implementation class_X
void function_C (class_X *cx)
{
//code...
}
#end
instantiating class_X:
#implementation someOtherViewController
- (void) viewDidLoad {
[super viewDidLoad];
class_X *cx = [[class_X alloc] init];
cx.intProp = 123;
cx.arrProp = #[#"one", #"two", #"three"];
function_C (cx); //does this not cause some sort of recursion?
}
#end
To have some naming conventions: "class instances" is akin of ambiguous. There are
instances (or instance objects) having a class.
classes, akin of type for an instance object.
class objects
So I assume that you want to use "instance objects of class X", when you write "class instances".
To your Q:
No, there is no overhead. Objective-C is a class-based programming language in contrast to JS that is prototype-based. That has the consequence that every instance has all instance methods that are declared as instance methods by the class. Therefore they are stored only a single time for all instances. The memory footprint for the methods does not depend on the number of instances are created. It is a one-timer. (The memory footprint for properties depends heavily on the number of instances.)
It is completely safe to pass references to instances to a function. Moreover the function can be defined everywhere. Of course, it has to see the interface of the class f the passed instance, probably via an import.

self concept ,if i use self in class method not in instance method

#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.

Which one is initialized, property or its instance variable

Suppose I have a property called myPropertyName defined in my class MyClassName. Manual memory management is used throughout this post.
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject {
#private
NSObject* myPropertyName;
#public
}
#property (nonatomic, retain) NSObject* myPropertyName;
// Some methods prototypes are here
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
#synthesize myPropertyName;
// Some methods are here
#end
I'm confused with usages such as the place of myPropertyName declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized -(void)init method for my class myClassName.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
This one is calling myPropertyName setter, but I'm not sure what is the name of the instance variable being used in the setter, myPropertyName (since I've declared a #private field named myPropertyName) or _myPropertyName (people say that this one with underbar is the default)?
myPropertyName = [[NSObject alloc] init];
Does this initialize the instance variable of the myPropertyName property? If I don't have #synthesize myPropertyName = _myPropertyName;, would it be wrong since the default instance variable for the property is said to be _myPropertyName.
_myPropertyName = [[NSObject alloc] init];
Is _myPropertyName still declared as the instance variable for my property myPropertyName even if I use #synthesize myPropertyName; and #private NSObject* myPropertyName;?
In my understanding, a property is just a name (such as myPropertyName), there should be some instance variable encapsulated to be used in actual operations in the code, such as assigning values.
First off, I highly recommend reading Apple's documentation on properties, also linked by nhgrif. However, I understand docs can be a bit dense reading material (though Apple's, I find, are not so bad), so I'll give a brief overview of properties here.
I like examples, so I'm going to rewrite your two classes in a bit more current form.
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject
#property (nonatomic, strong) NSObject *myPropertyName;
// method prototypes here
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
// some methods here
#end
The class MyClassName now has a property called myPropertyName of type NSObject *. The compiler will do a lot of work for you for "free" in this instance. Specifically, it will generate a backing variable, and also generate a setter and getter for myPropertyName. If I were to rewrite the two files, and pretend I'm the compiler, including that stuff, they would look like this:
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject {
NSObject *_myPropertyName;
}
#property (nonatomic, strong) NSObject *myPropertyName;
- (void)setMyPropertyName:(NSObject *)obj;
- (NSObject *)myPropertyName;
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
- (void)setMyPropertyName:(NSObject *)obj
{
_myPropertyName = obj;
}
- (NSObject *)myPropertyName
{
return _myPropertyName;
}
#end
Again, all of this is happening for "free": I'm just showing you what's happening under the hood. Now for your numbered questions.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
First of all, you should probably be using Automatic Reference Counting, or ARC. If you are, you won't be allowed to call autorelease. Ignoring that part, this works fine. Excluding the autorelease, this is exactly equivalent to:
[self setMyPropertyName:[[NSObject alloc] init]];
Which, if you look at the second .m file I wrote out, above, will basically translate to:
`_myPropertyName = [[NSObject alloc] init];
myPropertyName = [[NSObject alloc] init];
As written, this code will give a compiler error, since there is no variable called myPropertyName in this class. If you really want to access the instance variable underlying (or, "backing") the myPropertyName property, you can, by using its real name:
_myPropertyName = [[NSObject alloc] init]; // note the underscore
But most of the time, it's better to use the setter, as in point 1., since that allows for side effects, and for Key-Value Coding, and other good stuff.
_myPropertyName = [[NSObject alloc] init];
Oh. Well you got it. See point 2.
You mentioned that:
I'm confused with usages such as the place of myPropertyName declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized -(void)init method for my class myClassName.
In case it hasn't been made clear, a property is something of an abstract concept; its data is stored in a normal instance variable, typically assigned by the compiler. Its access should usually be restricted to the setter and getter, with important exceptions. To keep this answer short, I won't go into more detail than that.
One more thing: as nhgrif mentioned, you don't need to use the #synthesize keyword anymore. That is implicitly understood by the compiler now.
If you're not sure about any of this, post a comment or, better yet, read the docs.
Let's take this example:
#property NSString *fullName;
If in the implementation, we override the setters and getters, and in these setters and getters, we don't use an instance variable fullName, it is never created. For example:
- (NSString *)fullName
{
return [NSString stringWithFormat:#"%# %#", self.firstName, self.lastName];
}
- (void)setFullName:(NSString *)fullName
{
//logic to split fullName into two strings
//self.firstName = etc
//self.lastName = etc.
}
In this example, there is no instance variable for fullName created.
This is according to Apple's Official Documentation
If, however, you don't override both the setter and getter, an instance variable is created.
As a sidenote, you can declare a property readonly, and then simply overriding the getter (without using the variable) will prevent an ivar being created. Likewise, you can declare a property writeonly and just override the setter.

IOS: call a method in another class

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.