detecting and preventing crashed on older iOS (Suspecting EventKit) - iphone

Dear Scholars.
I have created a simple application using the latest SDK (4.2.1), Which runs smoothly and error free on all devices with iOS 4.x.x.
Lately I am getting some comments from users with older iOS version complaining the application is crashing on start, on Apple's crash log I see nothing at all.
Pushing my investigation forward, the only suspect I have at the moment is the use of EventKit class, which if memory serves, where introduced only after iOS4.
I am using it very lightly in one of my classes, and it works perfectly on iOS4.2.1
#import <EventKit/EventKit.h>
//some time later
[self setADateInCal: [MyTimeArray objectAtIndex:0] :formatterDate];
Thus my Questions:
Can this be the issue that crashes my application on iOS < 4 ?
How can I prevent it without dropping the feature for people with iOS4
In general, How can I test this? I have the latest official iOS on my device and SDK, the simulator is limited to how back it can go in regrading to iOS version... any magical way to do so?

1.) Yes. If it wasn't in the API in <4.0 than anyone not running >4.0 will crash.
2.) Test to see if the class is available using NSClassFromString (Google for examples) and respondsToSelector in correspondence to see if the method you want is available to use in the OS version the client is running. You will also probably need to weak link the EventKit framework (again Google for how to do this).
3.) The only real way to test this is to keep a device at the OS you want to test. Personally, I have an old iPhone that I never update running 3.1.3 for things just like this. Alternatively, you can keep old installs of xcode+iOSSDK on different partitions or something and use their simulator. (for future updates i guess since you obviously haven't done this for <4.0). But no, there is no magical way to do this. sorry.
edit for clarity on Number 2: Basically you will check to see if the class/method you want is available on the OS version you are currently running, if it is you can use it, if not you will have to find a work around (omit completely or do it another way that is compliant with older versions).

Yes it could be causing the crash. Issues with missing libraries do not report anything in the apple crash log.
To prevent it from happening you need to do two things,
Weak link the event kit library in xcode.
Check for its existence in your code with something like
,
if(!NSClassFromString(#"EKEventKit")){
//do stuff with event kit
}
The only way to test on the actual iOS version is to get hold of a physical device running ios < 4.

Related

iOS App with Static Lib crashes ONLY on launch of Archive Build loaded Ad Hoc. Can't reproduce in Debugger

I realize this is a stretch and I can't give much info to help but I am reaching for anything. My App has been under continuous development for 3 years and never seen anything like this. I recently submitted a small point release to Apple for Release, and twice now it has been rejected for Crashing on Launch on ALL their devices?
The Crash reports point to some code in static library but the key lines are not getting symbolicated. Tried Atos no luck.
The key point is that I have 7 devices I have tested the app on in every mode I can think of, in particular no connection to anything: Wifi-OFF, AirplaneMode-ON, Location services-OFF. I can NEVER simulate what they claim to be seeing, which is App crashes on launch every time?!
I found one report in the AAPL Dev Forums that sounded similar, but he never got any explanation as to what was up. After he submitted an app with loads of logging in it out of desperation and asked them to send the logs. They got that version and... approved it in hours.
Anyone have ANY ideas. I NEED to get this release out.
NOTE: Resolved
This turned out to NOT be a weak link issue. We only saw the crash when running the App using Ad Hoc distribution of the Archive version as Brad suggested... so that was helpful.
However the resolution turned out to be some compiler flags which I listed here:
https://stackoverflow.com/a/10302012/754494
I'll repost and expand upon my comment from above so that this question can have an accepted answer.
I recently came across a case similar to this when building my GPUImage framework. It appears that the build process is slightly different when archiving than when building and directly installing an application on the device via Xcode.
This can be exposed by building and archiving the application, then choosing to distribute it for ad hoc or enterprise distribution. Take the .ipa and place it in iTunes and manually load it on one of your test devices that way. The behavior of an application prepared in this manner may differ from one built and installed through Xcode, and should be closer to how a build submitted for review will act.
In my case, the problem was due to a lack of proper weak linking. On SDKs newer than iOS 4.3, you should no longer need to weak link whole frameworks if you wish to conditionally use classes and functions that are present in newer SDKs but missing in older ones. If you target 4.0 and higher, the linker should now perform class- and function-level weak linking.
However, this was failing for people using my static library, which does runtime checks for the presence of the new texture cache functions in iOS 5.0, but it only failed in these archived builds. I never saw it in all my testing against 4.x devices, because that was done by installing via Xcode. In the end, I needed to have users explicitly weak link the entire Core Video framework in order to get applications using this framework to run properly when archived and installed via iTunes.
Note that this wasn't due to the Release vs. Debug build configurations, because I tried switching between these in my build schemes when deploying to the device through Xcode and it made no difference there. Something else is different in the way that archived applications are built and linked.

Latest Reachability.m (Example code version 2.2) compatible with iOS 3.0?

Does anyone know if version 2.2 (the latest) of Apple's iOS 'Reachability' example code will run on iOS 3.0?
I want to support iOS 3.0, and Reachability.h and .m is the first non framework code I'm using in my app. In my own code I usually read the docs for all methods I use, and use respondsToSelector: to implement methods that won't run on 3.0.
When people use third party code, how do they confirm which iOS it supports without checking every method individually against the docs?
Alternatively, does anyone know how I can get my hands on the old version of the example code? (Reachability version 2.1 might help.)
I don't mean to snipe an answer from #Matt and #Martin, but I feel like this question deserves an answer for posterity. If they come back and post their comments as answers please feel free to accept them.
Anyway, my own answer is that I would highly advise against using Apple sample projects directly in a production application, especially Reachability. Many of their examples are badly written and, as you've noticed, outdated. I've filed a lot of bugs against them without many results.
That said, one other point is that you should really think twice about relying on Reachability for control logic. If you just want to notify the user when their connection changes or something, okay. But don't rely on what Reachability says to decide whether to try communicating with the network or not. It's often wrong about your network status. Just open up a connection, and if it succeeds great, otherwise you'll get an error response letting you know there's no connection.
EDIT - Regarding your other question about how to tell what IOS a third party app supports. The answer is, unless they've documented it, you might not be able to. Best indicator is usually taking a look at the build target's "Base SDK" and "iOS Deployment Target" settings. Base SDK will be the latest iOS version they've built against, and Deployment Target will be the earliest iOS version they support.
Cheers

Check for new SDK calls?

iOS development is now done using only the latest SDK.
Is there any way to search my code base for calls not present in older SDKs, generate warnings when compiling code that requires newer SDKs, or some other way to find where the code will fail on older iOS versions?
A workaround that broke compiling entirely would also be acceptable. This is not something I want to ship with, just something I want to do to verify that I've handled everything properly. The application seems to run on devices running earlier versions of iOS, but I'd like to be able to prove this.
No, I don't believe that there is a good way to find new calls not available in older SDK's. It's something I've wanted for a while.
The best thing I know of is to test your app thoroughly on a device running the oldest version of the OS that you plan to support.
It looks like this will do it...
Add this to your prefix:
#define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_3_1
Do not ship without removing this, though. In fact, you'll probably have to disable huge chunks of code to get your app to build this way. And even so, the coverage is nowhere near complete. But it's better than nothing.

What happens to existing iOS app when I update?

I have, after many months of work, finally got my app updated for iOS4.
The first release was complied for iOS3.2 and has been in the AppStore for a while, I was very impressed to see it continued to work and be downloadable for iOS4 users all this time, even though my version failed to compile for iOS4.
However, now I've got the new version (complied for iOS4.2) waiting for review - I'm unsure what will happen to the existing app! If it is used overwritten, what will people with old versions of iOS see? Am I closing the door to anyone without iOS4.2+?
Many thanks
Ben.
p.s. apologies if this has been covered - I did look and failed to find :-)
When you specify the minimum OS required in the bundle, that filters what users will be notified of the upgrade. So users of your app that have yet to upgrade the underlying OS will not get pushed the update.
You can actually specify the target OS Level to an earlier version. The app will be allowed to install on that and any newer version. Generally, Apple is very good about forward-compatibility.
As Peter said, you probably don't want to compile it to only run on 4.2. If you added features that use newer versions of iOS, you can actually do a check prior to calling the method (I've done this with gesture recognizers) to ensure that the running OS version is capable. If you don't validate the OS, the app will simply crash on users with too-old operating systems, which could cause Apple to reject it.
Also, 4.3 is almost out, so you might as well wait a week :)
If your app only supports 4.2+, then only users with a device with 4.2+ iOS will be able to install and use your app. The version currently on the store will be overwritten. In short, yes you are "closing the door" to anyone with a lower version iOS.

Updating iPhone app from OS3 to OS4

I want to update my app to make use of the multitasking functionality and local notifications available in OS4. My question is, if I update my app and make it only available for OS4 and above does this mean that if someone is running OS3 on their phone they won't get the update? or they will get a warning that they need to update their OS? What I don't want to happen is for them to update their app to find it no longer works? If the final situation is what will happen, how do I write the code to find out what OS is being used?
Thanks
If they try to update on the device, then they won't even see an update that doesn't run under their OS version.
However if a previous customer updates their apps using iTunes on their Mac or PC, then iTunes may show them any new update. If they download that, iTunes will blow away its copy that is compatible with their current device/OS combination. The new copy shouldn't overwrite the working one on their device. But if the user ever needs to do a restore, or deletes the app and wants to reinstall it, they're probably out of luck unless they have really good backups and know how to use them.
If you update your app to be 4.0 only, and also mark your app as 4.0-only in the Store, then people will not even see your update.
You can have the best of both worlds by designing the app to use 4.0-specific features only on 4.0 devices. Weakly link 4.0-only frameworks, and in your code use [object respondsToSelector:#selector(thisOnlyWorksInOS4:)] to test for 4.0 features before using them (or, in the case of multitasking, use the multitaskingSupported property of UIDevice, since not all 4.0 devices support multitasking). Alternatively, UIDevice also provides a systemVersion property.
This blog post explains these techniques fairly well, including weak-linking frameworks: http://blog.federicomestrone.com/2010/07/18/base-sdk-deployment-target-weak-linking-and-import/