What's the easiest way to determine inside a method if it has been called the first time since app start? - iphone

I have a method where I do some startup animations. The method gets called many times during usage of the app, but on it's first call it needs to do some special things in addition.
Are Singletons the way to go? Maybe there is also an better way, instead of measuring how many times this method was called, and storing that in an ivar.

- (void)someMethod {
static BOOL hasBeenCalledBefore = NO;
if (!hasBeenCalledBefore) {
// perform setup
hasBeenCalledBefore = YES;
}
// do other stuff
}
Extra work may be required if you're using threads, but that's the basic idea.

Why isn't that initialization code in the constructor? Maybe you need to factor that method out into it's own class which uses the constructor to handle the init block you mention.

An amendment to chuck's answer (pretty much correct)
His works and answers your question, but another option you could use (assuming it didn't need access to any of the variables being passed to that method) would be to take the code out of your method and put it in a static initializer. It will only be executed when the class is first loaded and will isolate what is essentially completely different pieces of code.
If you want it called for every new class, use Chuck's answer but with a member variable, or use a class initializer.

Related

Best way to do init without repeating code?

Each view class has multiple init methods - ones already included as part of UIView, and then additional ones - and each of them set up the same elements in the same way. I therefore usually have them all running a [self initialSetup]; method, which includes the setting up of all of these elements.
The problem i've ran into is that if a subclass also has an initialSetup method, it would override the superclass initialSetup method, and thus the superclass would have to have the method be public in order to still function. This causes problems with organisation, as the method should never be called other than from init, so has no reason to be public.
You've hit upon a problem that there's no perfect fix for. What you'd ideally have is a method that can't be subclassed in the normal sense, that's accessible only to instances of that exact type of class.
Where this is a risk, the normal practice seems to be to incorporate the class name into the setup method. So instead of initialSetup you'd have something like myViewSubclassInitialSetup.
You can also add something like this at the top of your method:
NSAssert([self isMemberOfClass:[ThisClass class]],
#"IniitalSetup called by sub- or superclass")
Then your debug builds will raise an exception if a subclass or superclass ends up calling your init method. That'll give you a place for a breakpoint and a stacktrace that should allow you to find the problem very quickly.
It won't add any code to your release builds.
Change the name of initialSetup to something like initialSetupClassName - subclasses, even if they accidentally used the same pattern, would not use the same name as they had a different class name.
You can also use an "_" prefix for private methods you would rather not be called, but the subclasser may do that also.
It sounds like you are missing a designated initializer. Designate one initializer as the official one that actually performs the setup, and have all the others just call that with some degree of customization. Usually the designated initializer will be the one with the most detail — for example, if you have init, initWithName:, initWithName:age: and initAsFiveYearOldNamed:, the designated initializer will be initWithName:age: and the other initializers would just call that method with the arguments filled in appropriately.
Unfortunatly Objective C doesn't provide a way to achieve that in a "clean" way. The ideal solution would be a protected method. But that's not possible in Objective C
Apple had this problem, when they were creating the UIGestureRecognizer. There were some methods they really didn't want to get called by somebody, but which had to be overwritten by subclasses. The way they chose to deal with this, was to create a seperate header file (UIGestureRecognizerSubclass.h), that contains a category to the original UIGestureRecognizer with those "protected" methods. The additional header is only to be imported by subclasses (i.e. for subclassing purposes). See UIGestureRecognizer Class Reference for some details.
Of course that doesn't prevent anybody from misusing the additional header file, but at least it clearly states your intention and keeps your code well structured. Also you won't be "bothered" by autocompletion for the additional methods, when just using the class.
Personally I only use an additional header, if it is extremely important that nobody calls it directly. In most cases I think it's ok to use public methods and make a note for what it's inteded. The iOS Framework also has many of these cases. F.e. many methods of UIViewController's viewDidLoad etc.

How to use MKLocationManager (a Private API) in iOS

I need to call
[[MKLocationManager sharedLocationManager] _applyChinaLocationShift:newLocation]
in my iOS app.
I believe MKLocationManager is a private class, and there does not seem to have a MapKit/MKLocationManager.h file.
I'm not targeting App Store. It's there any way I can use that private API?
Update at 2011-6-23
I really need the answer, or could I de-complie the iOS SDK?
100 reputation is almost all I have. Please help me.
If the above answer isn't working for you, this may be because the entire class is private (including it's header). Here's an alternative approach using some runtime trickery; you must be sure that the signature is correct but we can use some defensive coding to avoid a crash.
First, unless you are calling this just once, I'd wrap up the code in a helper method:
// in some header file, you may want to give the method a prefix too
CLLocation *ApplyLocationManagerChinaLocationShift(CLLocation *newLocation);
You can now use NSClassFromString to obtain a reference to the class and performSelector to perform the method. We can try and make sure the method exists first to be on the safe side:
CLLocation *ApplyLocationManagerChinaLocationShift(CLLocation *newLocation)
{
id sharedLocationManager = [NSClassFromString(#"MKLocationManager") performSelector:#selector(sharedLocationManager)];
SEL theSelector = #selector(_applyChinaLocationShift:);
// this will ensure sharedLocationManager is non-nil and responds appropriately
if (![sharedLocationManager respondsToSelector:theSelector]) {
return nil; // fail silently - check this in the caller
}
return [sharedLocationManager performSelector:theSelector withObject:newLocation];
}
I haven't run the above code but it should do the trick. If for some reason the #selector() calls do not work (I think they should), then you can replace them with NSSelectorFromString() calls instead.
You can simply create the method description yourself, essentially creating your own category on MKLocationManager. By defining how the private method looks you make it callable. But you must be certain about it's signature, because if you are off then your app will just crash.
This category could be put in it's own .h file or if you only use it in one place right above the #implementation.
#interface MKLocationManager (china)
- (CLLocation *)_applyChinaLocationShift:(CLLocation *)newLocation;
#end

vs [mpk5 weaponAttachments]

I'm able to make the method for the call [self weaponAttachments:mpk5] but I don't like having to call self. I think [mpk5 weaponAttachments] is more natural and is easier to read.
The problem I'm having is I need to pass in the weapon (mpk5) in order to use it, which I can do with the first method but not with the second one. Does this mean that I need to subclass NSDictionary in order to be able to use a statement like [mpk5 weaponAttachments]? If so, how do I get ahold of the caller "mpk5" so that I can use it inside the method?
EDIT
I apologize for not putting this in the first time but my objective is to have [mpk5 weaponAttachments] return an NSDictionary or NSArray. Right now I have NSDictionary *attachments = [self weaponAttachments:mpk5]; which works but it just doesn't seem like the best approach.
So firstly, your two calls are a little mixed up:
[self weaponAttachments:mpk5] calls the weaponAttachments method, passing in the variable mpk5.
But [mpk5 weaponAttachments] is either asking the mpk5 object to return the weaponAttachments property or is asking the mpk5 object to run a method called weaponAttachments (I'm simplifying here - it's always a method, but if you're using properties you probably won't realise this as Objective-C will create them for you).
These are fundamentally different things.
On to the brunt of your question:
I don't like having to call self
...unfortunately, if you're working in an object-oriented language you're going to have to get used to this. Say I have a class called mySimpleClass, and a method inside that class called doSomething. Writing this:
[mySimpleClass doSomething] would be what we call a static method. Whereas calling [self doSomething] from within an instance of mySimpleClass would be an instance method.
If you're unsure of the difference between static and instance methods you should probably step back and take a look at some of the basic guides out there.

Design: Passing on class instances or using singletons?

My app project contains several helper classes that serve all kind
of different purposes (eg time/date/calculation, db access, ..).
Initiating these classes is quit expensive since they contain some
properties that need to be filled up from the database or need to be
recalculated each time an new instance is created. To avoid performance
problems I tend to initiate each of these classes in the application delegate
and pass these on from viewController to viewController.
This has worked for me for some time but I'm finding now that the more
complicated the app is getting the more problems I'm bumping into.
Mostly problems related to classes getting entangled in a circular reference.
I would want to know how I could solve this properly, I alread thought about
turning each helper class into a singleton, and use the singleton instead of
passing a class instance around. But since some helper classes are depended on
each other I'll have singletons that call other singletons, I can't seem to
figure out if this would lead to other problems in the end.
Anyone any advice on this?
The problem with singletons is that they make it harder to mock and unit test your application. You should decouple your dependencies; and if you do somehow need a singleton (which should be very, very rare) then consider having the singleton implement an interface that you can mock for testing purposes.
Whenever I'm tempted to use a singleton, I re-read Global Variables are Bad and consider whether the convenience is really worth putting up with this (slightly) paraphrased list of problems:
Non-locality of methods and variables
No access control or constraint checking
Implicit coupling
Concurrency issues
Namespace pollution
Memory allocation issues
Unduly Complicated Testing
Singletons are basically global variables, and it's a bad idea to create a global variable just to avoid passing things around. Then again, often the right thing to do is simply to pass objects around from one class to another. The trick is figuring out the minimum amount of data you can pass to minimize the coupling. This is where well-designed classes are important. For example, you rarely need to pass an NSManagedObjectContext because you can get it from any NSManagedObject.
Now, let me address the specific case of your expensive-to-create objects. You might try pooling those objects instead of creating them every time one is needed. Database access is a good example of this. Rather than allocating a database connection every time you ask for one, you grab one out of a cache. Of course, when the cache is empty, you need to allocate one. And, for memory reasons, you should be willing and able to empty out the cache when the system asks you to.
That the object is expensive to create shouldn't matter to the user. That's an implementation detail, but it's one that you can design around. You do have to be careful because only objects that don't have mutable state can be handled this way, so you may have to rethink the design of your classes if you want to go this route.
Why don't you just make your app delegate a factory for the expensive-to-create instances? Each time a view controller needs an instance of the helper class it ask the appDelegate for it.
Personally, I usually using singleton.
In my opinion, it make the code cleaner...
And I am sure that class instance is unique.
I use it to have single point access to resource
Edit : Seems I'm wrong !
what about the flexible implementation ?
static Singleton *sharedSingleton = nil;
+ (Singleton*)sharedManager
{
if (sharedSingleton == nil) {
sharedSingleton = [[super alloc] init];
}
return sharedSingleton;
}

Memory leak using (void) alloc

I have seen a similar line of code floating about in Apples code:
(void)[[URLRequest alloc] initializeRequestWithValues:postBody url:verifySession httpHeader:nil delegate:self];
URLRequest is my own custom class. I didn't write this and I think the guy that did just grabbed it from Apple's example. To me this should leak and when I test it I'm pretty sure it leaks 16 bytes. Would it? I know how to fix it if it does but wasn't sure as it was taken from Apple's code.
EDIT: The problem was with the SDK, not the above code. See answer below for further details
Thought I might update this as after further testing and the release of iOS4 it has changed.
The above code doesn't leak and the memory footprint of the App returns to normal even after 200 iterations of the code. The leak did occur in iOS3 but was very small, in iOS4 it has completely disappeared both in simulator and device.
Some might wonder why you would want to implement this code but it works and make sense when dealing with lots of different NSURLConnections throughout your code running simultaneously.
Yes. This is a leak, which can easily be fixed by adding an autorelease:
[[[URLRequest alloc] initializeRequestWithValues:postBody url:verifySession httpHeader:nil delegate:self] autorelease];
Perhaps a better fix would be to create a class function that does this:
#interface URLRequest
{
// ...
}
// ...
+ (void) requestWithValues:/* ... */
// ...
#end
Then you could simply use [URLRequest requestWithValues: /* ... */] without invoking alloc.
Not at all sure what this code is supposed to accomplish. It does appear to break every single convention about initialization methods. What's the point of returning a void pointer from an initialization method? The entire point of an initialization method is to return an object. Where in Apple's code examples did you see this?
Having said that, I don't see why it would leak. Since it doesn't return an object there is nothing to leak external to the method. There might be something internally that leaks.
Edit:
It basically does an NSURLConnection.
Because we are submitting a lot of
forms with a lot of different values
we put it in an external class. All
the delegate methods like
didFailWithError: are in NSURLRequest
and connectionDidFinishLoading just
passes the data to its delegate. So it
doesn't really need to return anything
as it is done through a delegate
method.
Yeah, you need to redesign this. At present, this method is just a disaster waiting to happening. If nothing else, everyone else looking at this code will be utterly confused about what you are doing.
If you have no need to retain the object created, then move its allocation and clean up entirely within a method. Change the method name prefix from "initialize" to something like "setup", "configure", "acquire" etc so the name doesn't imply that it creates and returns and object.
If you need a one shot instance of a particular class, use a class method like Michael Aaron Safyan suggested (again without initialize in the name.) The class method should internally initialize an instance, perform the operations needed, return the data to wherever, then dealloc the instance.
That way, you won't have to worry about leaks and everyone else who may read your code (including yourself months down the road) will immediately understand what the code does.