objectForKeyedSubscript: crash on iOS 5.1 - objective-c

I'm running some code that does a [NSDictionary objectForKeyedSubscript:] and it's crashing on iOS 5, but not iOS 6. I am using xcode 4.5.2 and compiling against the iOS 6.0 SDK.
I assumed that this would work on iOS 5 since it's just a compiler feature? Am I wrong about that? I can just write my own versions of those functions, but I'm worried that something else is wrong since I would expect it to work.

NSDictionary reference for IOS in Apple developer
Available in iOS 6.0 and later.

OK, I'm going to answer my own questions, although I don't completely understand why it was failing.
Using objectForKeyedSubscript: and the like works fine running in iOS 5 (as long as it was compiled against the iOS 6 SDK).
The problem was I named a function +(void)load and making objectForKeyedSubscript: calls in this function causes an assert due to the method not being found.
This was an naming error on my part because the load method is called before the App is fully running. I have changed the name of my function and all is well.
I assume +load is being called before something with NSDictionary is fully inited. Odd that it works under iOS 6 and just not iOS 5.
Maybe that's not odd.

There is a workaround for pre-iOS6 SDKs
Checkout question here: Is there any way to get the neat Objective-C literal indexing feature in Xcode 4.4?

Related

Discover calls to methods not available in earlier iOS versions

I am building my app using iOS 5.0 as base SDK and iOS 3.0 as deployment target.
I know I need to check for existence of methods and classes when I work with features that are not available in the earlier iOS versions, but lately I've lost a few hours on a problem just to discover I was calling a method not available in some iOS versions. I simply did not notice it was a new method and did no check before to call it. The app of course compiled with 0 errors and 0 warnings.
This is a big problem because if I forgot some other check somewhere in the app, I will not know it until I or, worst, some user will activate that specific part of code.
Maybe I am missing something, is there some compiler option I can set to detect the calls I make to methods not available in the iOS deployment target? How do you deal with such a problem?
This link might point you in the right direction. Supporting mutiple ios Versions in your apps. It explains how to deal with taking advantage of the newer ios features while maintaining backwards compatibility. Hope that helps.
The only way to check for compatibility with a prior version of iOS, currently, it to test the app on an old non-updated device running that version of the OS.
If you can't find a device that old, even just to borrow for short time, then there may not be a good buiness reason to set the Deployment target that low.

making app compatible with previous iOS versions

I just released my app but I am only able to make it compatible from 4.3 and up.
When I try to go any lower than 4.3 (xcode), it says I need to add code to make this work.
Does anyone know how to do this or has any suggestions? I would like my app to be compatible with 3.0 and onwards.
Thank you very much
You have to reach the least common code, what I mean by this is that you must find all the methods that are all incompatible within all of these versions of the OS. After that you will have to find each and every of it's functional equivalents. Then you can use conditional statements to check for every version and see what fits better or you can use the respondsToSelector method inherited from the NSObject class. In the end you have to test it on each device you are targeting :P
You can run this checkup list that I have always liked.
Edit:
I think I misunderstood your question though it has already been mentioned, be sure to check your deployment target in your build settings.
Checklist:
In your project's build settings…
Did you set the "iOS Deployment Target" to iOS 3?
Did you include the armv6 architecture in both, the built and the valid architectures?
In general:
Do you link to any framework that is not supported on iOS 3?
Do you use any methods, classes or other features that have been added later?

about iOS target version and SDK version

iOS SDK is upgrading, and some new tech will appear, i.e, block is new tech.
So question is if "block" based implementation also can be distributed to lower target version or older iPhone ( 3G or first generation ) ?
how to cope with those issues ?
The usual way to deal with this sort of issue is to selectively enable features at runtime based on the current OS version. However, this can be very complicated to manage.
Query the current OS version at runtime
Use weak linking
Dynamically create the class
Call the new features only if the new class is present
For example:
Class optionalClass = NSClassFromString(#"NSArtificialIntelligence");
if (optionalClass) {
id optionalObj = [[optionalClass alloc] init];
// ...
}
The following documentation describes the process in detail:
Configuring a Project for SDK-Based Development
Using Weakly Linked Classes in iOS
You specifically mention blocks. This feature requires support from the compiler and Objective-C runtime, so it will not be available at all on older systems.
You must weak link to libSystem.B.dylib if you are using blocks for iOS4 or later. Because blocks are able to compile with the latest iOS SDK but iOS2,3.0 and 3.1 don't have blocks runtime.
iOS 4 app crashes at startup on iOS 3.1.3: Symbol not found: __NSConcreteStackBlock
(Besides, you can use blocks for iPhone 2.2+. Please take a look at plblocks.)

Dealing with deprecated symbols and methods when building for multiple iOS versions

I'm a c++ developer who is transitioning into the iPhone world, and I would love to get help around something.
Let's say for example, MPMoviePlayerController used to post the MPMoviePlayerContentPreloadDidFinishNotification notification in iOS 3.1 and earlier.
However, now this notification is deprecated.
I want my app to be able to run on every iPhone that has iOS 3 and above.
If I'm developing using base sdk 4.2, when I'm installing my app on an iphone with iOS 3.2 what will happen? Does the app comes with the sdk linked to it (like mfc static link for example)?
If I understand correctly, on iPhone with iOS 3.2 for example, that notification will still get called. (If i'm calling a function on an earlier sdk, assuming it's not statically linked like I asked above).
Does that mean that if I'm writing a new app now, I still have to take care of those deprecated notifications?
I can't get my head around this and would appreciate any explanation.
Thanks
If you use a symbol that was included with iOS 4.2 on a device that is running 3.2 you will encounter a crash.
The way to get around this is to use new symbols conditionally based on whether or not they're available at runtime.
Eg.
if (&NewNotificationSymbol != NULL)
{
// awesome, it's not NULL, we can use it
}
else
{
// not so awesome, we'll use the old, deprecated one
// but at least we won't crash
}
The same approach can be used for Classes that are new in 4.x when running on 3.x too:
if (NSClassFromString(#"MyAwesomeNewClass") != nil)
{
// awesome, it's not NULL, we can use it
}
else
{
// not so awesome, we'll use the old, deprecated one
// but at least we won't crash
}
As a rule of thumb, you should always compile and link against the latest iOS SDK provided with the developer tools and then set your Deployment Target build setting to the oldest version of iOS that you wish to support. Then use these conditionals to make use of new features and gracefully fallback without crashing if they're not available.

Android and Objective-C

I'm completing a project for the iPhone entirely written in Objective-C. I'd like to port this for Android too.
While the user interface of the iPhone and the Android OS are very different and will need different code, can I some how import the core of my code (ie. the black box that does the thinking) as is to Android as part of some Java code?
I have no familiarity with bridging between Objective-C and Java even though I have written in both.
You got luck! Phil Hassey has recently ported his own game from iPhone to Android within a week and wrote up what he did steps by steps. Here is his journey: http://www.philhassey.com/blog/2010/08/03/porting-galcon-using-the-android-ndk/
You could have a look at Apportable which allows to generate an Android app from an existing Objective-C code base. See this article too.
there is a fork of the gcc that supports objective-c on the android by patching the NDK on
http://code.google.com/p/android-gcc-objc2-0/. But it's considered beta at the moment and i'm not sure if jni/java bridges are already implemented
I have been doing a lot of work on this front — for example by creating my own C++ base framework that does not depend on STL (called Platform Core) and writing the core of the next version of my iOS app with that, so that I can easily port it to Android and whatever else has a C++ compiler and strikes my fancy.
I suggest having a (ick, I can't believe I'm about to say this, but eh), ahem, having a C++ core (there, I said it!) so it can be easily ported.