objective c help - calling methods? - objective-c

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? :)

Related

Objective C - Weak reference to super class?

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

How to call method in same class

I have a superclass, SuperClassYeh and a subclass, SubClassYeh. I have method inheritTest in SuperClassYeh and I override inheritTest in SubClassYeh. I start the program running by calling method testSuperAndSelf in SubClassYeh. This method would call another method, fromYEH in SuperClassYeh. In fromYEH, I would like to call inheritTest in SuperClassYeh. How do I do that? Using [self inheritTest] calls the inheritTest in SubClassYeh, not SuperClassYeh.
Here's the code fragment to start the whole thing running
SubClassYeh *testing = [[SubClassYeh alloc] init];
[testing testSuperAndSelf];
Here's the code fragment for SuperClassYeh
- (void) fromYEH
{
[self inheritTest]; //Calls the inheritTest in SubClassYeh, not SuperClassYeh
}
- (void) inheritTest
{
NSLog(#"Testing Indicator. Inside SuperClassYEH inheritTest");
}
Here's the code fragment for SubClassYeh
- (void) inheritTest
{
NSLog(#"Testing Indicator. Inside SubClassYeh inheritTest");
}
- (void) testSuperAndSelf
{
[super fromYEH];
}
You can't, and this is the intended behaviour of inheritance in Objective-C.
If self is an instance of SubClassYeh, then
[self inheritTest]
calls the SubClassYeh implementation of inheritTest (if there is one),
no matter from where that message is sent (subclass or superclass).
The only difference between [super fromYEH] and [self fromYEH] is that the lookup
for the "fromYEH" message starts at the superclass, but it does not change the fact
that self is an instance of SubClassYeh.
And you cannot prevent a method from being overriden in Objective-C
(see How to avoid superclass methods getting overridden by sub class in objective - c or other Q&A's about that topic).
The only thing that you can do in the superclass is to choose method names
that are not overriden accidentally, e.g. by prefixing the method name
with the class name, as suggested here: https://stackoverflow.com/a/17209309/1187415.
If you can call [super fromYEH] from SubClassYeh, what is the problem in calling [super inheritTest] the same way?
Even it is a quite strange behavior, you can try something like this(didn't test it, actually)
- (void) fromYEH
{
bool isSubClass = [self isKindOfClass:[SubClassYeh class]];
if(isSubClass == YES)
{
[super performSelector:#selector(inheritTest)];
}
else
{
[self inheritTest];
}
}
Anyway, even if this code will really do the trick, I still think that this is very bad practice.
EDIT:
Checked this in XCode. It will not do the trick =) So upvoted Martin's answer =)
I found the solution. Instead of calling [super fromYeh]in testSuperAndSelf, change the receiver to the superclass. Use [[[[SubClassYeh superclass] alloc] init] fromYEH]. Inside method fromYEH, the inheritTest of SuperClassYEH would be called.
Here is the code fragment for method testSuperAndSelf in SubClassYeh. Other codes remain the same.
- (void) testSuperAndSelf
{
[[[[SubClassYeh superclass] alloc] init] fromYEH];
}
Just for the record...
What you want to do isn't as difficult as you think, if you look at it from a different perspective.
All you have to do is define a C function and call that.
- (void) fromYEH
{
inheritTest(self); //Calls the inheritTest() in SuperClassYeh
}
void inheritTest(SuperClassYeh *self)
{
NSLog(#"Testing Indicator. Inside SuperClassYEH inheritTest");
}
- (void) inheritTest
{
inheritTest(self);
}
(I love the names... ;)

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

Preventing subclasses overriding methods

Assume there is an object that initialises like so
- (void)doInit
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
[self doInit];
return self;
}
and it has a subclass which is inited in a similar way
- (void)doInit
{
NSLog (#"In SubClass init");
}
- (id)init
{
self = [super init];
[self doInit];
return self;
}
Now if I create an instance of child class then I receive the following output:
In SubClass init
In SubClass init
when really, what I meant to happen is
In BaseClass init
In SubClass init
Is there a way to mark doInit to say that it shouldn't be overridden or do I need to create a unique name for all methods in a subclass?
I'm not entirely sure how I haven't come across this issue before, but there you go.
Edit:
I understand why this is happening, I hadn't expected that the base class would be able to call the overridden function.
I also can't just call [super doInit]; from the Subclass method because the BaseClass still needs to call doInit so that creating an instance of BaseClass will still work. If I called [super doInit], I'd still end up getting SubClass's doInit called twice.
It appears the answer is no and I'll just have to uniquely name each doInit like doBaseClassInit and doSubClassInit.
If you have a method that you don't want to by dynamically bound (i.e. don't want a subclass method to be called if it exists), you need to do it as a C function instead. So, you could do this instead:
In the base class:
static void DoInit(BaseClass *self)
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
if (self) {
DoInit(self);
}
return self;
}
in the subclass:
static void DoInit(SubClass *self)
{
NSLog(#"In SubClass init");
}
- (id)init
{
self = [super init];
if (self) {
DoInit(self);
}
return self;
}
Note that both the DoInit methods are marked as static, so they are only visible each compilation unit (.m file) and don't conflict with each other.
You could, perhaps, try something like this in your base class. It would mean any time the init implementation inside BaseClass executed, the doInit implementation for BaseClass would be called.
- (void)doInit
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
Class baseClass = [BaseClass class];
SEL selector = #selector(doInit);
IMP baseClassImplementation = class_getInstanceMethod(baseClass, selector);
baseClassImplementation(self, selector);
return self;
}
As I mentioned in my comment, if that's the narrowness of your need this should work as it gets around the dynamic method lookup involved with sending a message. Hope this helps!
EDIT:
Disclaimer - if you're in this situation it's probably not a good sign for the longevity of your design. This technique will get you up and running for now but please document it carefully, and consider ways to refactor your code so this is no longer used. Consider fixes like these to really be used only when extremely urgent.
The reason why you are not getting the "In BaseClass init" console message is because your subclass is not calling the super's implementation of doInit.
If you don't want doInit overridden the 'best' way to avoid doing so is to not publish the existence of this method. Remove it from your header and uniquely name the method so that a collision is unlikely. For example, many of the private methods in Apple's frameworks have a leading underscore. So, for example, you could call your method _doInit and it will be very unlikely that a subclass accidentally create it's own overiding implementation.
Nope, there's no enforceable way to prevent a subclass from overriding a method. The best you can do is to avoid putting it in the public header file for the class so someone is not likely to try to override it. If the method has to be public, you just put a note in the documentation for the method that it shouldn't be overridden or that subclasses should call super's implementation whichever the case may be. You'll find these kind of instructions all over in the documentation for Apple's own classes.
If you want your subclass to use the baseclass version of doInit then in the subclass don't declare a doInit method. Here's what I mean:
ClassA:
#interface ClassA :
-(void) doInit;
-(id) init;
#implementation
-(void) doInit {
NSLog(#"ClassA doInit");
}
-(id) init {
self = [super init];
if (self != NULL)
[self doInit];
return self;
}
ClassB
#interface ClassB : ClassA
-(id) init;
#implementation
-(id) init {
self = [super init];
if (self != NULL)
[self doInit];
return self;
}
And really you don't need to override the init method as well unless there's some special code that you want that class to do.

How to call a method from another method in Objective C?

Can someone answer me how to call one method into another in Objective C on Xcode
The basic syntax for calling a method on an object is this:
[object method];
[object methodWithInput:input];
If methods returns value:
output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];
More Detail
EDIT:
Here is a good example that how to call method from other class:
OBJECTIVE C - Objective-C call method on another class?
Example:
SomeClass* object = [[SomeClass alloc] init]; // Create an instance of SomeClass
[object someMethod]; // Send the someMethod message
You get a pointer to an object that implements the other method and send the appropriate message (e.g. [otherObject doSomething]).
For example:
#implementation view1
(void)someMethod
{
......code of method...
}
#implementation view2
(void)fistMethod
{
view1 *abc = [[view1 alloc]init];
[abc someMethod];
[abc release];
}
I hope you got it.
If you have 2 functions inside class(.m file):
-(void) func1{ }
-(void) func2{ }
If you want to call func2 from func1, you cannot just call func2();
instead just include self
That is:
-(void) func1{
[self:func2];
}