Not going into method - ios

I'm just learning iOS development but I have experience in C++ and I'm having an issue where my I call a method on an object but that object is not being called. Here is my code:
#implementation EXCoursesViewController{
EXNetworkingController *_networkController;
}
-(instancetype)initWithStyle: (UITableViewStyle)style{
self = [super initWithStyle: style];
if(self){
self.navigationItem.title = #"Title";
[_networkController createSession];
[self fetchFeed];
}
return self;
}
[_networkController createSession] doesn't seem to actually call the createSession method in the EXNetowrkingController I made. I'm not sure why this is happening. Any help would be greatly appreciated.

I'm not sure why this is happening.
Most likely, it's because _networkController is nil. It's apparently an instance variable, but you haven't given it a value at the point in -initWithStyle: where you're trying to send it a message.
To fix the problem, just create an EXNetworkingController instance and assign it to your ivar before using:
_networkController = [[EXNetworkingController alloc] init]; // or use the correct initializer
[_networkController createSession];

You are not doing the alloc and init for your EXNetworkingController. What i recommend is make your createSession method as public and call it. It can be called through the EXNetworkingController class name itself.
Do something like this:
+(void)createSession{
//Your createSession code goes here
}
You just have to replace the minus(-) which is in front of the -(void)createSession method with plus(+)
Then in your EXCoursesViewController class inside the initWithStyle replace [_networkController createSession]; with [EXCoursesViewController createSession];
And you no longer require to make an object of your EXCoursesViewController.
So you can remove EXNetworkingController *_networkController;
Hope this helps. Thanks.

Related

do something before [super init] in objective-c

I would like to set a member variable in a derived object before i call [super init].
All I can find is that you should not do such a thing. My worakround, to do it anyhow, works, but actually I like to know what the consequences are when bending the rules. Or even better if there is a correct way to deal with this.
The Details:
I have several wrappers that bind a c++ object to an objective-c objec (mostly UI...View or UI...Controller)
#interface my_scrollview : UIScrollView
{
my_c_class* m_p;
}
-(id) initWithFrame:(CGRect)frame wrapper: (my_scrollview*) pWrap;
-(void) setContentOffset:(CGPoint)contentOffset;
#end
#implementation dwin_scrollview_ios
-(id) initWithFrame:(CGRect)frame wrapper: (my_scrollview*) pWrap
{
m_p = pWrap; // illegal but works?
return [super initWithFrame: frame];
//m_p = pWrap; // to late because [super init...] already called overriden func.
}
In my overwritten setContentOffset-method I need to access my C++-Object.
The Problem arises because the initWithFrame internally initializes its content using setContentOffset. So this method is called before I could "legaly" set up the link to my c++-object.
I can implement my overrides with a check if m_p is set(luckily it's initialized to nil). But I have to synchronize the state of the view and my c++-object after the the init-method. In this example this is no big deal but other such realtions are much more complicated and I end up with lot of code that repeats steps of the initialization or otherwise brings me back in sync, although before the [super init...] I know I was in sync.
Is there a pattern to solve this correct (and elegant)?
Is it really so bad to int the pointer before the call to [super init..];?
(I assume one consequence is that this crashes if [super init] returns nil...? any other cases?)
Thanks in advance
Moritz
There is nothing magical about init methods in Objective-C. alloc returns an object of the class that you want, with all instance variables initialized to 0 / nil / NULL / 0.0 etc. Each init method then just executes the code that the developer has written.
There are things that are obviously stupid, like setting an instance variable of the superclass, then calling [super init] which promptly overwrites it. And you need to be aware that init doesn't necessarily return self, but a different object, in which case everything you've initialised in the base class before calling [super init] will be gone.
// illegal but works?
No, it's not illegal. It's perfectly legitimate, although unconventional, to do stuff to an object before its superclass' initializer has been run. It may still lead to unexpected behavior and bugs, but it's not illegal per se. Sometimes it's even necessary, for example when you want to perform some computation and delegate the result of that computation to the superclass' initializer.
You are using wrong init
try this:
-(id) initWithFrame:(CGRect)frame wrapper: (my_scrollview*) pWrap
{
self = [super initWithFrame: frame];
if (self) {
m_p = pWrap;
}
return self;
}

Trying to create a custom initializer method

So I know there a bunch of questions like this but none of their solutions seems to be helping me.
Let me start of by saying I am using storyboards so I would use initWithCoder instead of initWithNibName:.
Now that we got that bit out of the way. So, simply I want to pass an object to another view with a custom initializer.
So in my second view I would have code like this:
- (id) initWithMyLifeChangingObject: (MagicType *)object {
//Apparently this is important
self = [super init];
//Do some stuff with my magical object
//You know the story
return self;
}
And as the story goes you need to call your world class init:
[SecondClass alloc] initWithMyLifeChangingObject:object];
But initWithMyLifeChangingObject: isn't recognized and gives me a build error saying it is not in existence... so what do I do.

Objective-c: Questions about self = [super init]

I have seen self = [super init] in init methods. I don't understand why. Wouldn't [super init] return the superclass? And if we point self = [super init], are we not getting self = superclass?
Here's an example code fragment
- (id)init
{
if (self = [super init]) {
creationDate = [[NSDate alloc] init];
}
return self;
}
Hope someone can clarify this for me. Thank you.
Assuming that MyClass is a subclass of BaseClass, the following happens when
you call
MyClass *mc = [[MyClass alloc] init];
[MyClass alloc] allocates an instance of MyClass.
The init message is sent to this instance to complete the initialization process.
In that method, self (which is a hidden argument to all Objective-C methods) is
the allocated instance from step 1.
[super init] calls the superclass implementation of init with the same (hidden)
self argument.
(This might be the point that you understood wrongly.)
In the init method of BaseClass, self is still the same instance of MyClass.
This superclass init method can now either
Do the base initialization of self and return self, or
Discard self and allocate/initialize and return a different object.
Back in the init method of MyClass: self = [super init] is now either
The MyClass object that was allocated in step 1, or
Something different. (That's why one should check and use this return value.)
The initialization is completed (using the self returned by the superclass init).
So, if I understood your question correctly, the main point is that
[super init]
calls the superclass implementation of init with the self argument,
which is a MyClass object, not a BaseClass object.
As you have Question self = [super init] in the if Condition suggest a specific meaning.
First of all [super init] gives the initialization of the superclass of the existing class which is in use currently. Using [super init] gives the super class initialization which shows that object exist of the class.
Now when you use self = [super init] that means you are assigning the class to the self for the further utilization of the same class.
And at the end you put it in if condition as if(self = [super init]) this means you are checking whether the object of the class exist of not to prevent the foul behavior of the application.
I think it is clear now!!!
#MartinR has a very good answer. But do you ever wonder why "[super init] calls the superclass implementation of init with the same (hidden) self argument. (This might be the point that you understood wrongly.)" works in his 3rd point ?
Here is the excerpt from Big Nerd Ranch guide 3rd edition, chapter 2 Objective C that clarifies this point
“How does super work? Usually when you send a message to an object,
the search for a method of that name starts in the object’s class. If
there is no such method, the search continues in the superclass of the
object. The search will continue up the inheritance hierarchy until a
suitable method is found. (If it gets to the top of the hierarchy and
no method is found, an exception is thrown.)”
“When you send a message to super, you are sending a message to self,
but the search for the method skips the object’s class and starts at
the superclass.”
This code shows how iOS Runtime performs this task
objc_msgSendSuper(self, #selector(init));
Every method that you declare has two hidden parameters: self and _cmd.
The following method:
- (id)initWithString:(NSString *)aString;
is converted by the compiler to the following function call:
id initWithString(id self, SEL _cmd, NSString *aString);
see this link for more:
http://www.cocoawithlove.com/2009/04/what-does-it-mean-when-you-assign-super.html
Self = [super init];
According to JAVA, this mean a pointer to instance itself so object can message itself.
Same meainng of Self here in objective C,
According to JAVA, Super mean that allow to access base or parent class
Same meainng of Super here in objective C,
Now init instance to to complete the initialization process.
I would think of it as, init'ing all the supers variables etc, then you get to init your extended classes variables before it is returned.
[super init] is the same as [self superclass_variant_of_init]
If you want to send a message to superclass, there is another approach (without using runtime library):
[[self superclass] init];
From Apple's Documentation:
Because an init... method might return nil or an object other than the one explicitly allocated, it is dangerous to use the instance returned by alloc or allocWithZone: instead of the one returned by the initializer. Consider the following code:
id myObject = [MyClass alloc];
[myObject init];
[myObject doSomething];
The init method in the example above could have returned nil or could have substituted a different object. Because you can send a message to nil without raising an exception, nothing would happen in the former case except (perhaps) a debugging headache. But you should always rely on the initialized instance instead of the “raw” just-allocated one. Therefore, you should nest the allocation message inside the initialization message and test the object returned from the initializer before proceeding.
id myObject = [[MyClass alloc] init];
if ( myObject ) {
[myObject doSomething];
} else {
// error recovery...
}

Why relaodData call the viewDidLoad

I am maintaining an app developed by someone else and I got a strange behaviour when debugging it. when allocating a view controller object from another class, it will call viewDidLoad, in viewDidLoad, I make call to another method in which I fill in an array:
- (void)viewDidLoad
{
[super viewDidLoad];
[self fillArray];
}
-(void)fillArray{
arrayProduct = [[NSMutableArray alloc] init];
//fill in the array from server
[self.objTableView reloadData];//refresh the table view
}
The strange behaviour is, once [self.objTableView reloadData]; statement is executed, the viewDidLoad gets called again. Why is this happening? Thanx in advance.
You can solve this issue by using flag.
Declare on BOOL variable and make it true before call the reloadData method. and in viewDidLoad check if variable is true then don't init your array.

Custom UITextField delegate

I have a uitextfield subclass and in the init method and setDelegate I have this:
- (void) setDelegate:(id<UITextFieldDelegate>)paramDelegate{
[super setDelegate:paramDelegate];
MRAAdvancedTextFieldDelegate *limitedDelegate = [[MRAAdvancedTextFieldDelegate alloc] init];
self.delegate = limitedDelegate;
}
I am using ARC, but this results in a BAD_ACCESS. Any ideas?
You write self.delegate = limitedDelgate within your setDelegate: method. This is exactly the same as calling [self setDelegate:limiatedDelegate]. Since you are within the -setDelegate: method itself, you are causing infitine recursion. Hope this helps!
EDIT: per your comment about your intention, override it like this:
- (void) setDelegate:(id<UITextFieldDelegate>)paramDelegate{
MRAAdvancedTextFieldDelegate *limitedDelegate = [[MRAAdvancedTextFieldDelegate alloc] init];
[super setDelegate:limitedDelegate];
}
But I don't believe it's a good idea to do this - you should have your client code pass in instances of your delegate instead.
self.delegate = limitedDelegate;
is turned into
[self setDelegate:limitedDelegate];
by the compiler, resulting in an infinite loop. Solution: instead of using the property, use the instance variable instead in the custom setter method:
delegate = limitedDelegate;

Resources