Please can anyone try to help me on this issue.
I have one requirement like, I want to call a class method from static constructor (+(id)initialize) method like below that will intialize the CLLocationmanager.
My problem is how can I give a delegate in that class method and how to get delegates method called.
+(void)initialize
{
[self fetchLocation];
}
+(void)fetchLocation
{
mLocation = [[CLLocationManager alloc]init];
mLocation.delegate = self;
mLocation.desiredAccuracy = kCLLocationAccuracyBest;
[mLocation startUpdatingLocation];
}
If I allocate the same class instance and add as delegate its crashing.
1) You can't call [self fetchLocation] from a static method like +initialize. That's because there's no self there (self refers to the current object, which is something you don't have in static methods.)
2) The line mLocation.delegate = self doesn't make sense for the same reason.
To fix your design, you can do one of the following things, depending on what makes the most sense in your app:
Make your class a singleton, and make that singleton a delegate for CLLocationManager
Put the location manager init code in the appropriate -init method of your class
Related
Today I was going through some of the online codes and I found some NSObject Class.
Some are having:
- (id)init
{
self = [super init];
return self;
}
And some doesn't have it.
Then I also tried this in my Sample Code. I was totally confused. Before this I was thinking that we must write -(id)init method to instantiate a NSObject Class. But now it is working without it.
Here are my some of my doubts:
is -(id)init method really necessary?
What happens if we don't use it.
If we don't write init method even then my code works. Why?
Having an empty -init has absolutely no function.
NSObject already has -init method. And methods in Objective-C are inherited.
It's the same as overriding any other method and just call super:
- (void)someMethod {
[super someMethod];
}
You'll find answers to your questions in the Apple documentation on initializers. I'd recommend you go through those materials, they will clarify a lot of things.
To sum up the documentation with regards to your questions:
is -(id)init method really necessary?
If you don't need to perform extra logic when your class is instanced, then you don't need to implement an init in your class.
What happens if we don't use it.
Even if you don't need to implement it in your subclasses, you need to call it when creating a new object, e.g. [[MyClass alloc] init]
If we don't write init method even then my code works. Why?
As I wrote above, you don't need to declare one for your class, but you need to call it. Otherwise your code might not properly work.
[super init] is highly recommended to give a chance for the superclass to also properly configure the newly created object.
Not calling super init is an error, and results are undefined. (Bad things my happen)
-init() is initializer of NSObject. If a user creates a Person Class which inherits NSObject. It can override this initializer, or one can create their own custom initializer as show below
eg.
class Person : NSObject
{
let name:String
//Initializer inherited from NSObject
override init()
{
super.init()
}
//Custom Initializer
init(withName name:String)
{
super.init()
self.name = name
}
}
I havea Utility class that uses class methods. I am trying to refer to self in the class method but can't. I was wondering how would I declare the following in a class method:
[MRProgressOverlayView showOverlayAddedTo:self.window animated:YES];
self.window it says member reference type struct objc_class *' is a pointer; maybe you meant to use '->'
Another problem that relates to not being able to call self is how would I refer to a declared #property in my .h in a class method in my .m.
Here is my class method:
.m
+ (void)showHUD
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
[MRProgressOverlayView showOverlayAddedTo:self.window animated:YES];
//I would preferably like to call my property here instead
}
.h
#property (nonatomic) MRProgress * mrProgress;
The whole point of a class method is that it is not part of a specific instance. Inside of a class method, self is the class.
If you need to be tied to a specific instance, then it should be an instance method. If you want a static method that accesses a specific instance, then pass that instance (self) to it (though it's hard to imagine many cases where that makes sense).
In the above example, showHUD should be an instance method almost certainly. If that doesn't make sense for some reason, then it should be:
+ (void)showHUDForWindow:(UIWindow *)window;
You can then call it as showHUDForWindow:self.window and use that as needed.
You can use a singleton pattern. Singleton pattern assumes that the only instance of your class exists. Since it's the only instance, you can then use it from class methods.
Example implementation:
+ (MyClass*)sharedInstance {
static dispatch_once_t once;
static MyClass *sharedMyClass;
dispatch_once(&once, ^ {
sharedMyClass = [[self alloc] init];
});
return sharedMyClass;
}
Then you can access the shared instance via [MyClass sharedInstance], for example:
+ (void)doSomethingCool {
[[self sharedMyClass] doSomething];
}
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.
Following my previous post about UIViewControllers designated initializer initWithCoder I have another question about the argument aDecoder passed into the protocol method.
Here is the code in question:
#implementation WhereamiViewController
- (id)initWithCoder:(NSCoder *)aDecoder //we're overiding the superclasses (UIViewController) inititalizer
{
self = [super initWithCoder:aDecoder];
if (self){
//create location manager object
locationManager = [[CLLocationManager alloc] init];
//there will be a warning from this line of code
[locationManager setDelegate:self];
//and we want it to be as accurate as possible
//regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//tell our manager to start looking for its location immediately
[locationManager startUpdatingLocation];
}
return self;
}
I was curious about aDecoder so renamed it to see if my code would still work and it did. What I want to know is what exactly is being passed into initWithCoder as an argument? It seems like nothing is in my code. Is the argument just part of the method and has to be shown even if nothings being passed into it? Other times I have created designated initializers I've done it like this:
self = [super init]
init is NSObjects designated initializer right?
This is the only part of the code I don't understand. I see I'm calling my superclasses initializer and then implementing it with additional custom code / making it selfs (whereamiviewcontroller) value.
I did set a marker and look in the logs to see if anything would catch my eye but had no luck with that.
Thanks in advance
Regards
You can see the -initWithCoder: method in action when you try to initialise your view controller instance from nib or storyboard. In this case Cocoa Touch will decode the controller elements from the xml using UINibDecoder instance by -initWithCoder: initialiser.
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...
}