How to avoid multiple allocating of CLLocationManager instance? - iphone

I am using core location framework inside my app and sending updated location to server in didUpdateToLocation method and the view where i am allocating the CLLocationManager instance is the second view after login and this view is called from login view and releasing CLLocationManager in dealloc method but every time i am coming from login screen then didUpdateToLocation method calling twice and thrice depending on how many times i am coming from login view so whats the problem is and how can i avoid this?

If you want to avoid multiple allocations of your CLLocationManager instance, define the instance as a property of your appDelegate
Each time you need to get this instance you will do
YouAppDelegate *appDelegate = (YouAppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.yourLocationInstance;

I usually just use a singleton for this type of thing. Just define a class method (using a + vs a - on the method definition). Here's an example of a singleton definition:
+(id)sharedLocationManager
{
static BCLocationManager *sharedLocationManager;
#synchronized(self)
{
if (!sharedLocationManager)
{
sharedLocationManager = [[BCLocationManager alloc] init];
}
return sharedLocationManager;
}
return sharedLocationManager;
}
Basically you define a static instance of your class and only initialize it if it doesn't exist. With a singleton, you never access the instance init function. Always assign the result of the singleton accessor to the appropriate pointer like so:
BCLocationManager * testInstance = [BCLocationManager sharedLocationManager];
Now all you have to do is include the appropriate header.h and everyone in your application can see that single instance of your location manager. As long as you don't use an instance of init, you'll never create more than one.

Related

what is a proper way to maintain a network connection that different views will use?

I want to connect to some arbitrary device via wifi from a "connection" view. When pressing "back" and returning to the main menu, I want the connection I created to still exist(so that other views of the app can send/recive messages through it like ssh or telnet). Is it a good idea to create a connection (with say CFNetwork or such) in a separate thread or NSOperation and pass a reference to this thread to the main menu view controller?
You need to design your app in such a way that each separate group of functions are in a separate class. For example, as mentioned above, use a separate class for connections. You can use the Singleton pattern in order to create 1 instance only for your app to use from anywhere.
Also instead of worrying about NSOperations...which would be calls within your class, you can use a well-tested framework and off you go. You'll find it here with examples...
https://github.com/AFNetworking/AFNetworking
#interface NetworkConnections: NSObject
#end
#implementation NetworkConnections
(id)sharedInstance
{
// structure used to test whether the block has completed or not
static dispatch_once_t p = 0;
// initialize sharedObject as nil (first call only)
__strong static id _sharedObject = nil;
// executes a block object once and only once for the lifetime of an application
dispatch_once(&p, ^{
_sharedObject = [[self alloc] init];
});
// returns the same object each time
return _sharedObject;
}
(void) doSomething {
}
#end
Anytime you want to use that class:
[[NetworkConnections sharedInstance] doSomething];

What's the Best Way to Send Parameters to a UIViewController?

I ask this question because it appears that viewDidLoad gets called before the main block of the initializer does and the class variables I'm initializing in the initializer are turning up nil in viewDidLoad. For your reference, I'm doing this entire viewcontroller programmatically and I've created a custom initializer so I can take in various parameters to be used in my viewcontroller. My custom initializer calls UIViewControllers designated initializer of course.
Basically, I'm curious about what is the proper design pattern for sending in parameters to a UIViewController? I've read other threads about this and haven't really gotten a definitive answer. Should I just skip the initializer and set the properties manually (from outside the class)? That seems kind of bleh, I'd really like to send in some parameters and am curious how others go about doing this?
The reason viewDidLoad is called before initialization completes, is probably because you call the view method in the initializer. For example:
- (id)init
{
if ((self = [super init])) {
_thing = 123;
_other = self.view.frame.size.width / 2;
}
return self;
}
viewDidLoad is called when the view loads. And the view loads as soon as you call the view method (or access the view property, if you prefer). So you should avoid referencing the view in init.
To answer your question, I prefer to create an init method for my view controllers.
- (id)initWithThing:(MyThing *)thing thang:(MyThang *)thang
{
if ((self = [super init])) {
_thing = [thing retain];
_thang = [thang retain];
// ...
}
return self;
}
You can also use properties to set extra variables after initing. Personally I prefer to do this with optional properties only, though, and put required properties in the init method. That way I can't init the view controller with an invalid state.
I encapsulate the state of my controllers in an additional state object. So the controller usually has ivars for the GUI elements and a reference to this state object.
State objects are handled by a StateManager object on my delegate. So instead having a controller referencing another controller and set variables directly, all changes go through this manager. A little more work but way less messy.
Any class is able to retrieve the state for any other controller and change it. This is the purpose of some controllers (eg: choosing a video from youtube happens on a dedicated controller). But usually is just one class getting a state to push the next controller with initWithState:. The pushed controller then applies the state to its GUI in viewDidLoad or changes this state object passed from the previous class.
The StateManager keeps a dictionary of all the state objects. I keep the state object graph light, eg: I store a reference to a image, but not the image itself. The real beef of the application is in Core Data, I only use all this to handle the GUI state. The StateManager listens for the application resign event and saves the state dictionary to disk using NSCoding. The state object ivars are always nil or some meaningful value, no dangling pointers.
I'm working on my 2nd iPhone app and this seems to be working, but I wonder too how other people does it. Any input is welcome.
Basically you should have properties defined for your input data but add a custom init-function.
If you create a custom init-Method you should be fine - remember that initWithNibName:bundle: is the main initializer of UIViewController so this is what you want to call from your custom init-Method. viewDidLoad will always be called after your init-Method at the first usage of customVC.view (either from your code or via Framework):
- (id)initWithDataObject:(MyDataObject*)obj
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.dataObj = obj;
}
return self;
}

Calling methods in different classes

This question is semi-similar to the one asked here
But the difference is that I'm using cocos2d.
I have a method named screenshot in my AppDelegate. It's obviously used to take a screenshot. I want to call this method in another class, but simply doing [self screenshot]; isn't working out because I get the warning 'GameOver' my not respond to '-screenshot'.
All I want is for the screenshot method to be called in GameOver.
Thanks!
You can't call a method that does not exists - it will generate a runtime error.
If you want to call a method of AppDelegate from GameOver you should have a pointer to AppDelegate object if the method is not static:
[appDelegatePointer screenshot];
If the method is static
[AppDelegate screenshot];
I suppose you have only one object AppDelegate and you can make a static method
+(AppDelegate) sharedDelegate;
of class AppDelegate that will return your object singleton. And so you will be able to call screenshot method from GameOver object or from any other place like this:
[[AppDelegate sharedDelegate] screenshot];
Such thing is done in CCDirector, CCTextureCache, SimpleAudioEngine, ... classes in Cocos2D

addObserver questions, try to check if data is loaded

I have a ViewController that initializes another class that loads data into a mutable array and saves it as a property on itself.
here is my ViewController init code:
-(id) initWithCollectionID:(NSString *)aCollectionID {
if (self = [super init]){
collectionID=aCollectionID;
dataSource = [[CollectionListDataSource alloc] initWithCollectionID:collectionID];
}
return self;
}
once dataSource has loaded all of the data into it's property dataSource.collectionItems I set dataSource.loaded = #"true";
how do I use addObserver to watch that value and fire off a function in my ViewController?
something like this I'd assume:
[self addObserver:dataSource forKeyPath:#"loaded" options:NSKeyValueChangeNewKey context:nil];
Then what do I do?
As your code stands now, it will pause until the data is loaded regardless of whether you use notifications or not. It will not progress past:
dataSource = [[CollectionListDataSource alloc] initWithCollectionID:collectionID];
...until the CollectionListDataSource object has completed its own initialization (which I presume also means the loading its data) and returns an instance of itself.
If you want the CollectionListDataSource object to load while the view controller keeps on initializing, you will need to put the CollectionListDataSource object on another thread. However, you can't have an attribute object running on separate thread.
You seldom need to jump through such hoops. Unless this array is very large (10k+ objects) you most likely don't have to worry about. In most cases, you need the data before the view can function anyway so there's no point in letting the view go on without the data.
If you do need actually need to observe an attribute of another object, see Key-Value Programming Guide: Registering For Key-Value Observing for details.

How to tell if an object has already been allocated, so it isn't allocated multiple times?

Please be nice.. I am a noob with this stuff. I want to allocate and use an object through a method that I call many times, and instead of making it a global variable and allocating it in my initWithFrame method I want to alloc it in just the one method, and make it a local variable that I allocate then and use then.
You need to step back and think about how many different things need to access said object.
If it is everyone, then you should likely implement the shared instance pattern. Something like:
+ (MyObject *) mySharedObjectThatEveryoneUses
{
static MyObject *sharedInstance;
if (!sharedInstance) {
sharedInstance = [MyObject alloc];
sharedInstance = [sharedInstance init];
}
return sharedInstance;
}
Note that the above does not account for threading on initialization. I.e. if multiple threads simultaneously call the method for the first time, you might end up with multiple instances. Also note that the splitting of +alloc and -init is a pattern that is unique to this situation. Doing so avoids the situation where the -init method causes + mySharedObjectThatEveryoneUses to be invoked, creating a second instance before the assignment can happen.
Now, if you are talking about access within an object graph; access to the single instance within some subset of objects in your application, then you will need to have an instance variable somewhere that all of the objects can get to.
For example, say you are implementing a game where there is a Player object and that Player object has a bunch of Piece instances. When a Piece is created, you would typically have a property that refers to the owning player and that would be your single point of reference.
If you need something more transient, you should likely look to what should be your controller layer. I.e. there has to be some object somewhere that can act as a coordinator for the set of objects that need access to that single instance.
If I understood your question correctly, you're looking for a static variable. A static variable keeps its value like a global variable, but it "lives inside" a function like a local variable. Your function could look something like this:
+ (MyObject *)getSingletonObject {
static MyObject *obj = [[MyObject alloc] init];
return obj;
}
obj would be created the first time you called this method, but calling the method again would return the same object it had already created.
What you want is called a Singleton. You can read up on Apple's recommended way to create singletons here:
http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
Look for "Creating a Singleton Instance" in the "Cocoa Objects" section. There are a few more methods it's good to define beyond just a class level initializer.
I'm not entirely sure I understand your question, but you can't really allocate the same object many times.
Each time you want a new instance, you ask the Class object to allocate a new instance for you (yes, classes being objects themselves is mind blowing). So this code:
NSString* s;
s = [[NSString alloc] init];
s = [[NSString alloc] init];
Here you are creating two instances of NSString. This code is bad because we have alloc'd the first instance and have not released, and assigned its only reference (s) to a new instance. This would cause a memory leak.