Get super class instance in Objective C - ios

How can I get super class instance?
id superObject=super;
Xcode says, "Use of undeclared identifier super"

It's not completely clear to me what you are trying to do, but based partly on your comments to your own question here is a guess.
It seems you may be confused over super in both Objective-C and Java. Both these languages are based on inheritance where a subclass instance is also an instance of its superclass. In neither language is there the concept of a "superclass instance/object". The meaning of super in the two languages is essentially the same, but differs in detail due to the different way the two languages support hiding.
In Objective-C super is a keyword while self, which references the instance a method was called on, is a variable (and the equivalent of Java's this). The super keyword is used to call a method on self but to start the search for the implementation to call in the superclass instead of the current class. It is usually used by an overriding method to call the method it has overridden.
However in your comments you also write:
I want to add a target with a method implemented in super class
which suggests you are trying to use an API which uses the target/action pattern, e.g. NSControl and others.
If the method you wish to call is not overridden in the current class then simply passing self as the target will invoke the superclass method. For example:
#interface Base : NSObject
- (IBAction) actionOne:(id) sender;
- (IBAction) actionTwo:(id) sender;
#end
#interface Child : Base
...
#end
#implementation Child
- (void) setActionFor:(NSControl *)aControl
{
aControl.target = self;
aControl.action = #selector(actionOne:); // actionOne is NOT overridden in Child
}
...
However if your subclass overrides a superclass method and you wish to set the superclass implementation as the action then you must write a method in your subclass which invokes the superclass method. For example, expanding on the previous example and passing Base's actionTwo as an action in a Child method when Child overrides actionTwo:
#implementation Child
// override Base method
- (IBAction) actionTwo:(id)sender { ... }
// provide a way to directly invoke Base method bypassing override
- (IBAction) superActionTwo:(id)sender
{
[super actionTwo:sender];
}
- (void) setActionFor:(NSControl *)aControl
{
aControl.target = self;
aControl.action = #selector(superActionTwo:); // indirectly set Base's actionTwo
}
HTH

Your self in-turn consist your super. You can access your super properties through self.

There isn't a separate object that represents your "super" object. Self is an instance of your class, which is part of a class hierarchy. When you call a method using the super keyword, you're specifying that you want to use your super class's implementation of that method. If your subclass doesn't override a method defined in super, then performing the selector on self will trigger a miss on your class's method lookup table and find the method definition on your superclass.
So, the simple answer is you should be able to accomplish what you're trying to do through self =]

Here you are trying initialize object with a class, not with instance of this class.
May be something like this?
id instance = [super init];

Related

Designated Initializer?

what is this saying as stated in apples doc:
Sometimes the designated initializer of a superclass may be sufficient for the subclass, and so there is no need for the subclass to implement its own designated initializer. Other times, a class’s designated initializer may be an overridden version of its superclass's designated initializer. This is frequently the case when the subclass needs to supplement the work performed by the superclass’s designated initializer, even though the subclass does not add any instance variables of its own (or the instance variables it does add don’t require explicit initialization).
Apple's Documentation
Is it saying that i don't have to create a designated initializer for the subclass and the superclass designated initializer will suffice and if so how will the subclasses properties be initialized? and in what scenario if this allowed? How would that work?
Also if your overriding the DI how can you call that method from the subclass as the parent class has the same DI as you do? What does it mean that it needs to supplement the work?
Example:
There is a superclass A with an initWithName: DI.
Now you create subclass B. If you want the same DI and you don't need any additional initialization, then there is nothing to do with the init method. You simply call:
B *someBObject = [[B alloc] initWithName:#"A Name"];
This creates the B object and calls the initWithName: method from A.
Now if your B class needs to do supplemental work in the initWithName: method, then you add this to B.m:
- (instancetype)initWithName:(NSString *)name {
self = [super initWithName:name];
if (self) {
// do some additional stuff to initialize this "B" instance
}
return self;
}

Passing owner reference to created objects

I need to pass the reference of a view controller to one of the object it creates. I have the following piece of code where I instantiate my object
//Method in OwnerClass
- (void) someMethod{
SomeObject *obj = [[SomeObject alloc] init];
obj.instanceVar = self.iVar;
}
Now in SomeObject I want to access the owner(instance of OwnerClass) which created it.
//Method in SomeObject
- (void) callback{
[ownerObj callMethod] //ownerObj is the instance of OwnerClass that created an instance of SomeObj
}
I want to know how do I access the instance of OwnerClass inside instance of SomeObject. Of course, I can simply write a property inside SomeObject like
#property(nonatomic) OwnerClass *ownerReference;
and assign it when I'm initializing SomeObject and access it from there.
What I want to is if there is any standard way of getting the owner. Something similar to
self.parentViewController
which is Apple's standard way of obtaining the parent of a particular view controller.
There is no general, formal concept of "Ownership" for objects in Objective C or the iOS SDK. So no, there is no standard "magic" way of doing what you want.
it's wrong to pass a reference from view to another view..
if you want to call method in another controller you can use protocols and delegate

resolveInstanceMethod on super returns NO for a valid selector

I've implemented +resolveInstanceMethod on a class that subclasses NSDictionary. I will dynamically add methods to my class for certain cases, but I want standard NSDictionary methods to 'just work'.
I thought this would be the case if I just call [super resolveInstanceMethod:sel]; at the end of my method but it doesn't work.
+ (BOOL) resolveInstanceMethod:(SEL)sel
{
BOOL value = [super resolveInstanceMethod:sel]; // this is always NO!?
return value;
}
Why is this? How do I get my class to behave 'normally' for existing methods on the superclass?
What leads you to expect that -resolveInstanceMethod: would return YES for already existing methods? The release notes which introduced the new method say that the default implementation simply returns NO:
The NSObject class implements these methods with a default
implementation that returns NO today, though you should still invoke
it even if you're just directly subclassing NSObject.
In any case, it should never even be called for methods which are already present on the class. It's only called when you message an object with a selector which isn't already "resolved" to an implementation.

Creating class extension for a Class's private methods

I have created a Game Model as a class. I checked out this question about creating a class extension: Best way to define private methods for a class in Objective-C
What I have is some public methods - these are open for other VCs to use in the app.
I also want some private methods, that the classes public methods can make use of, but do not need to be open to the rest of the application as such.
I thought this could be accomplished by a class extension, adding an extra interface section in the implementation file but this doesn't appear to work.
Imp file:
#import "MESGameModel.h"
#interface MESGameModel ()
-(BOOL)checkIfGameAlreadyExistsAgainst:(PFUser *)opponentUser;
#end
#implementation MESGameModel
#pragma mark - Public methods
+(void)createNewGameAgainst:(PFUser *)user2 withCompletion:(void (^)(BOOL success))completionHandler{
Later on I have the declaration of the other private method:
#pragma mark - Private methods
-(BOOL)checkIfGameAlreadyExistsAgainst:(PFUser *)opponentUser {
What I am looking for is the ability to call for example [self checkIfGameAlreadyExistsAgainst...] within the public method (createNewGameAgainst).
Your createNewGameAgainst method is a class method (see the + in front of the method declaration). Your checkIfGameAlreadyExistsAgainst method is a instance method (see the - in front of the method declaration). To call checkIfGameAlreadyExistsAgainst from createNewGameAgainst you need to get an instance of MESGameModel. self inside of createNewGameAgainst references the class itself, not an instance of it.
You can use the form; your problem is understanding the distinction of class methods vs instance methods.
+ (void)createNewGameAgainst:(PFUser *)user2 withCompletion:(void (^)(BOOL success))completionHandler
Is a class method (note the '+') -- you do not need an instance of MESGameModel to call this method. However, you will have no instance of MESGameModel within the definition (or body of) that class method. You cannot use the instance methods, properties, or ivars of the MESGameModel because the instance of MESGameModel is absent in a class method.
self in this scope will be a special class which you can message but responds to the class methods.
- (BOOL)checkIfGameAlreadyExistsAgainst:(PFUser *)opponentUser;
Declares an instance method (note the '-'). An instance of MESGameModel may respond to this message, and within that method's definition, you will have access to the instance variables, properties, instance methods, and class methods of MESGameModel.
self will be an instance of MESGameModel which you can message, and responds to the instance methods.

how to forbid the basic init method in a NSObject

I want to force user to use my own init method (for example -(id)initWithString:(NSString*)foo;) and not the basic [[myObject alloc]init];.
how can I do that?
All other answers here are outdated. There is a way to do this properly now!
While it is easy to just crash at runtime when somebody calls your method, compile-time checking would be far preferable.
Fortunately, this has been possible in Objective-C for a while.
Using LLVM, you can declare any method as unavailable in a class like so
- (void)aMethod __attribute__((unavailable("This method is not available")));
This will make the compiler complain when trying to call aMethod. Great!
Since - (id)init is just an ordinary method, you can prohibit calling of the default (or any other) initializer in this way.
Note, though, that this will not insure against the method being called using the dynamic aspects of the language, for instance via [object performSelector:#selector(aMethod)] etc. In the case of init, you won't even get a warning, because the init method is defined in other classes, and the compiler doesn't know enough to give you an undeclared selector warning.
So, to ensure against this, make sure that the init method crashes when being called (see Adam's answer).
If you want to disallow - (id)init in a framework, make sure to also disallow + (id)new, as this will just forward to init.
Javi Soto has written a small macro to forbid using the designated initializer faster and easier and to give nicer messages. You can find it here.
tl; dr
Swift:
private init() {}
Since all Swift classes include an internal init by default, you can change it to private to keep other classes from calling it.
Objective C:
Put this in your class's .h file.
- (instancetype)init NS_UNAVAILABLE;
This relies on an OS define that prevents the method named from being called.
The accepted answer is incorrect - you CAN do this, and it's very easy, you just have to be a bit explicit. Here's an example:
You have a class named "DontAllowInit" which you want to prevent people init'ing:
#implementation DontAllowInit
- (id)init
{
if( [self class] == [DontAllowInit class])
{
NSAssert(false, #"You cannot init this class directly. Instead, use a subclass e.g. AcceptableSubclass");
self = nil; // as per #uranusjr's answer, should assign to self before returning
}
else
self = [super init];
return nil;
}
Explanation:
When you call [super init], the class that was alloc'd was the SUBCLASS.
"self" is the instance - i.e. the thing that was init'd
"[self class]" is the class that was instantiated - which will be SUBCLASS when the SUBCLASS is calling [super init], or will be the SUPERCLASS when the SUPERCLASS is being called with plain [[SuperClass alloc] init]
So, when the superclass receives an "init" call, it just needs to check whether the alloc'd class is the same as its own class
Works perfectly. NB: I don't recommend this technique for "normal apps" because usually you INSTEAD want to use a Protocol.
HOWEVER ... when writing Libraries ... this technique is VERY valuable: you frequently want to "save (other developers) from themselves", and its easy to NSAssert and tell them "Oops! you tried to alloc/init the wrong class! Try class X instead...".
-(id) init
{
#throw [NSException exceptionWithName: #"MyExceptionName"
reason: #"-init is not allowed, use -initWithString: instead"
userInfo: nil];
}
-(id) initWithString: (NSString*) foo
{
self = [super init]; // OK because it calls NSObject's init, not yours
// etc
Throwing the exception is justified if you document that -init is not allowed and therefore using it is a programmer error. However, a better answer would be to make -init invoke -initWtihString: with some suitable default value i.e.
-(id) init
{
return [self initWithString: #""];
}
Short answer: you can't.
Longer answer: the best practice is to set your most detailed initializer as the designated initializer, as described here. 'init' will then call that initializer with sane, default values.
Another option is to 'assert(0)' or crash in another way inside the 'init', but this isn't a good solution.
I actually voted up Adam's answer, but would like to add some things to it.
First, it is strongly encouraged (as seem in auto-generated init methods in NSObject subclasses) that you check self against nil in inits. Also, I don't think class objects are guaranteed to be "equal" as in ==. I do this more like
- (id)init
{
NSAssert(NO, #"You are doing it wrong.");
self = [super init];
if ([self isKindOfClass:[InitNotAllowedClass class]])
self = nil;
return self;
}
Note that I use isKindOfClass: instead because IMHO if this class disallows init, it should disallow its descendants to have it as well. If one of its subclass want it back (which doesn't make sense for me), it should override it explicitly by calling my designated initializer.
But more importantly, whether you take the above approach or not, you should always have appropriate documentation. You should always clearly state which method is your designated initializer, try as best as you can to remind others not to use inappropriate initializers in documentation, and put some faith in other users/developers, instead of trying to "save everybody else's asses" with clever codes.

Resources