Objective C - Weak reference to super class? - objective-c

I am trying to call a method on super class inside a block.
In order to avoid a retain-cycle I need a weak reference to super.
How would I get a weak reference to super?
[self somethingWithCompletion:^(){
[super doStuff];
}];
I tried the following but gives a compile error.
__weak MySuperClass *superReference = super;

You could define a helper method
-(void) helperMethod
{
[super doStuff];
// ...
[super doOtherStuff];
// ...
}
and then do
__weak MyClass *weakSelf = self;
[self somethingWithCompletion:^(){
MyClass *strongSelf = weakSelf;
[strongSelf helperMethod];
}];
A direct solution using the runtime methods looks like this:
__weak MyClass *weakSelf = self;
[self somethingWithCompletion:^(){
MyClass *strongSelf = weakSelf;
if (strongSelf) {
struct objc_super super_data = { strongSelf, [MyClass superclass] };
objc_msgSendSuper(&super_data, #selector(doStuff));
}
});
Disadvantages (in my opinion):
More (complicated) code.
According to the "Objective-C Runtime Programming Guide", you should never call
the messaging functions directly in your code.
Depending on the return type of the method, you would have to use objc_msgSendSuper or objc_msgSendSuper_stret.
For methods taking arguments, you have to cast objc_msgSendSuper to the proper
function type (thanks to #newacct).

Your problem can be solved by using an Objective-C runtime function objc_msgSendSuper to send a "supermessage" to weak self.
It's not possible to "get a weak reference to super", as super is a language construct rather than a separate object. Take a look at this explanation of super:What exactly is super in Objective-C?.

Related

Objective-C Blocks: Is it ok to modify self in an external method if called from a weak pointer to self?

Can you modify self from an instance method called from a weak self pointer within a block?
-(void)someMethod:(AnotherClassName *)anObject {
__weak MyClassName *weakSelf = self;
[anObject requestSomethingWithCompletion:^{
[weakSelf updateSomething];
}];
}
-(void)updateSomething {
self.something = #"update"; // Will this cause a memory leak?
}
So basically I am calling an instance method from the same class I am in, but I am doing it from a weak pointer and then changing self.
According to Apple's Programming with Objective-C Guide this is how to call a method on self within a block but it isn't clear weather I can directly modify self in that method.
If you know the answer based on something you've read before please include the source.
Thanks!
You can modify properties and call methods. There will be no memory leaks.
But your block is not thread safe now. If requestSomethingWithCompletion will run block asynchronously your class (self) could be deallocated during block execution and weakSelf will become nil. This could cause problems (depends on what does your block do). Good practice to avoid this is to write it following way
-(void)someMethod:(AnotherClassName *)anObject {
__weak MyClassName *weakSelf = self;
[anObject requestSomethingWithCompletion:^{
MyClassName *strongSelf = weakSelf;
[strongSelf updateSomething];
}
}
-(void)updateSomething {
self.something = #"update"; // No leaks here!
}

Objective-C: Self-variable understanding Issues

I want to know some features about self.
Which context have self variable in class method?
Why self.self allowed in init method?
First:
We have a class ExampleClass
#interface ExampleClass:NSObject
#property (nonatomic,strong) NSString* a;
+(ExampleClass*)createExampleClass;
#end
#implementation ExampleClass
-(id)init{
self = [super init];
if(self){
[self.self init]; #Allowed
[self init]; #Not Allowed ?
}
}
+(ExampleClass*)createExampleClass{
/*do work here*/
NSLog(#"Self: %# \n Class: %#",self,[self class]);
}
#end
In this example we will see something like this:
Self: ExampleClass
Class: ExampleClass
But why?!
And in init method [self.self init] allowed, but not allowed '[self init]'.
Why does this happen?
In a class method, self is the class. For classes [self class] simply returns self, so self and [self class] are basically the same thing there.
Calling [self init] in the init method doesn't make any sense, it would cause an infinite recursion. However, the compiler error you get is a restriction of ARC, if you'd use self = [self init], the error would go away, but it would still make no sense. You might do this in a different initializer method though, to call the designated initializer.
self.self is short for [self self] which does nothing but return self.
self in class method is the class object itself.
NSObject has self method which returns itself.
    See here:  https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/self
Self: ExampleClass // Name of the class.
Class: ExampleClass // Name of the meta-class object which is same with class object.
If you print pointer address, you will see two objects are different.
Here's nice illustration and description.
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
self.self.self.self.self.self is also valid :) or [[self self].self self].self.self

Calling an optional method in superclass (Objective-C)

I'm trying to create a generic implementation for the NSCoding protocol.
The code will be wrapped around in a macro the will implement NSCoding.
In order to implement the protocol, we need two functions:
-(void)encodeWithCoder:(NSCoder*)coder;
-(id)initWithCoder:(NSCoder*)coder;
A generic implementation of the initWithCoder function would be:
-(id)initWithCoder:(NSCoder*)coder {
if ([super conformsToProtocol:#protocol(NSCoding)])
self = [super initWithCoder:coder];
else {
self = [super init];
}
if (!self) return self;
self = [MyGenericCoder initWithCoder:coder forObject:self withClass:[__clazz class]];
return self;
}
The problematic line is self = [super initWithCoder:coder]; it will not compile since super does not respond to initWithCoder: when we use the in a class that its super does not implements NSCoding. Casting super to NSObject<NSCoding>* will not work with the LLVM compiler.
[super performSelector:(initWithCoder:) withObject:coder] will not work either since super == self, Which will result in an infinite loop.
How can I call [super initWithCoder:coder] in manner that will trigger the function in the superclass and will not generate a compilation warning / error?
You can use +instancesRespondToSelector: to find out if your superclass responds to the selector, and then objc_msgSendSuper() directly to actually call it.
#import <objc/message.h>
- (id)initWithCoder:(NSCoder *)coder {
// Note: use [__clazz superclass] directly because we need the
// compile-time superclass instead of the runtime superclass.
if ([[__clazz superclass] instancesRespondToSelector:_cmd]) {
struct objc_super sup = {self, [__clazz superclass]};
((id(*)(struct objc_super *, SEL, NSCoder*))objc_msgSendSuper)(&sup, _cmd, coder);
} else {
[super init];
}
if (!self) return self;
self = [MyGenericCoder initWithCoder:coder forObject:self withClass:[__clazz class]];
return self;
}
How can I call [super initWithCoder:coder] in manner that will trigger the function in the superclass and will not generate a compilation warning / error?
Just create two variants of your macro -- one for types whose superclasses adopt NSCoding, and another for those which do not.
Either that, or abstract the detail from yourself and derive from intermediate types which abstract the condition from your bases and adopts NSCopying -- then you can just call initWithCoder: on any such type.
#import <objc/runtime.h>
-(id)initWithCoder:(NSCoder*)coder {
Class superclass = class_getSuperclass([__clazz class]);
SEL constructor = #selector(initWithCoder:);
if (class_conformsToProtocol(superclass,#protocol(NSCoding))) {
self = class_getMethodImplementation(superclass,constructor)(self,constructor,coder);
}
else {
self = [super init];
}
if (!self) return self;
self = [MyGenericCoder initWithCoder:coder forObject:self withClass:[__clazz class]];
return self;
}

objective c help - calling methods?

Hey,
I am new to programming I wanted to know why is it always [self method];? I mean why is it that way could someone explain me why is it self and what is going on in the background? sorry if it is a stupid question
thanks,
TC
Basically, what self refers to is the object that you're currently in the context of. [self somemethod] means that you're invoking a method named somemethod in the class that self was initialized as.
For example, if you were to do something like this:
Foo *f = [[Foo alloc]init];
[f someMethod];
You'd be invoking someMethod on the Foo instance.
But if you're working inside of the class Foo, self serves as an explicit reference to the current object. In this case, you'd simply use [self someMethod] to invoke someMethod.
-(id) init {
if (self = [super init]) {
[self someMethod];
}
...
}
-(void) someMethod { }
Does that help?
[self method] calls the method of the calling class. For example, in the header file of your class,
#interface YourClass : NSObject {
}
- (void) myMethod;
then, you can call the 'myMethod' in YourClass by using [self myMethod]. Does it make sense?
During calling [self method], there is no any background working. [self method] is almost same the calling function in C. When you use [self method], 'method' in your class is just called right away.
Because [self method]; calls the -method method in the class from which it is called.
If you want kill John in ObjC:
[john sendBullet]
if you do sendBullet to myself (shortly self), it's a suicide
[self sendBullet]
got the difference? :)

Objective C init

Disclaimer, I'm new to Objective C. But I can't find this explained. I've seen two ways of implementing init:
- (id)init {
if ([super init]) {
return self;
} else {
return nil;
}
}
and
- (id)init {
if (self = [super init]) {
// do your init business here
}
return self;
}
so let's say i have:
myObj = [[MyObject alloc] init];
where MyObject class is a subclass of NSObject. in the second example, does init not return an initialized version of NSObject? so myObj would ... how would it know what it is? wouldn't it think it was an NSObject rather than a MyObject?
1) First version is just wrong. self should be always assigned with value returned by super initializer, because init<...> of super can return another object upon initialization (it's not unusual BTW). Second version is actually an 'official' way to implement init<...> methods.
2) 'wouldn't it think it was an NSObject rather than a MyObject'. myObj is instance of 'NSObject' and instance of 'MyObject'. It's the whole point of inheritance.
i just want to know, under the hood, how it does it.
It's pretty simple. 99.9% of all the classes you'll ever write will inherit from NSObject in some fashion. In the initializers, you're supposed to invoke super's designated initializer and assign it to self. Eventually, [super init] will be invoking -[NSObject init]. According to the documentation, that's implemented like this:
- (id)init {
return self;
}
So technically, if you inherit directly from NSObject, you're probably safe to not do the assignation of self = [super init];, because you know (and you're guaranteed) that this is equivalent to: self = self;, which is kind of pointless. Regardless, you should leave it in for consistency's sake.
However, once you start getting further down the inheritance chain, and especially when you're inheriting from opaque classes (ie, a class whose .m file you do not have), then things start getting shady. It is possible that you'll come across a class whose designated initializer looks something like this:
- (id) initWithFoo:(id)aFoo {
if ([aFoo isSuperFast]) {
[self release];
return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
}
self = [super init];
if (self) {
_foo = [aFoo retain];
}
}
This isn't as common, but it does happen. In this case, we're destroying self ([self release], to balance the alloc call that immediately preceded this) and instead returning a different object.