NSJSONSerialization crash with Facebook iOS SDK 3.5 - ios

After I updated Facebook iOS SDK from 3.2 to 3.5 I'm getting this error when running my app in a device with iOS older than 5 (eg 4.3.5).
dyld: Symbol not found: _OBJC_CLASS_$_NSJSONSerialization
...
Expected in: /System/Library/Frameworks/Foundation.framework/Foundation
I can avoid this crash if I set Foundation framework as Optional, but I don't think this is the best option.
Is there another way to make Facebook SDK works in devices with iOS previous to version 5?

From Facebook iOS SDK changelog v3.5:
http://developers.facebook.com/ios/change-log-3.x/
Removes support for iOS 4.* Facebook 6.0 dropped support for iOS 4.x. To stay in sync, the Facebook SDK is also does not support iOS 4.x.
So, if you update to Facebook SDK 3.5 you lose support for iOS 4.x

That class was not available until ios5 - look at the class reference in the Xcode documentation window. What you need to do is grab JSONKit, an open source class, and use it. Usage is mostly the same. You will need to build this class into your app then test dynamically if the apple class exists, then use the appropriate class, or just always use the open source class.
Note that JSONKit is not ARCified, so you need to set the appropriate compile flag for it if the rest of your app is ARC.
Edit: so you may be able to get clever and write your own stub that bridges calls to JSONKit in older releases. Conceptually you should be able to make this work, but my fear would be that if the FB code was developed for ios5 then there may be other Api problems lurking in the code too - and you old spend a lot of time continually trying to find and fix them.

Related

Xcode How to check if there is any API used in the whole project which is not available for the current development target

Recently my app was getting crashed on IOS8 because i have used an API which is only available for IOS 9 and above. I am wondering is there anyway to check the whole project and find out if I am using any API which is not available for the current development target. Something like the warnings for the deprecated APIs. Thanks.
In order to tell the compiler you want to support an earlier OS, you need to set the SDK to that earlier OS's SDK. If you set the SDK to iOS 8, then any time you use functionality from a later OS, you should get a compiler error.

Developing with deprecated frameworks

I have a general question as I found many frameworks are deprecated in iOS 9. Consider developing for iOS 7 and above with the latest Xcode and iOS SDK. I'm going to use UIAlertView which is deprecated in iOS 9 and replaced with UIAlertController. In my code when I want to show an alert, should I have to check for iOS version and provide a block of code using UIAlertView for iOS prior to 9, and another block of code for UIAlertController for iOS 9 and above?
The same goes for AddressBook and AddressBookUI frameworks which are replaced with Contacts and ContactsUI frameworks.
I know that many deprecated frameworks still work fine with new iOS SDK but sometime in future there will be a chance of not working fine.
What would be a good approach on this issue?
First off, UIAlertView was deprecated in iOS 8, not iOS 9.
Deprecated doesn't mean removed. It means obsolete.
As long as an API isn't deprecated in your Deployment Target, it should be safe to use. It's very rare for a deprecated API to actually stop working.
Like everything else, test to be sure everything works on each version of iOS your app supports.
When you drop support for iOS 7 in some future update of your app, you can replace all uses of UIAlertView with uses of UIAlertController.
Similar for AddressBook. Keep using it until your Deployment Target becomes iOS 9 then you can migrate to using the new Contacts framework.
Of course if a new API offers functionality that you wish to use on devices that support, feel free to do so. Just make sure you don't try to use newer APIs on devices with older versions of iOS.
Keep this in mind. There are apps that were written in iOS 2.0 seven years ago. Many of these apps still work under iOS 9.
Check iOS version first is a good way. Besides, you can use respondsToSelector method to check whether the new methods are supported on the (new) running devices.

App migration between different iOS versions

Currently, I'm in the middle of adapting my app for iOS 7.1 to support iOS 8.
During this process, it dawned more and more on me that I may have seen the relationship between SDKs and OS versions wrong all the time.
I'll tell you with a concrete example:
The UIViewControllerContextTransitioning protocol gained some more methods for iOS8. So in order to support the new OS, I started implementing the new methods in my ContainerViewController.
When I came across the - (UIView *)viewForKey:(NSString *)key method, I naturally checked the key against the UITransitionContextFromViewKey constant.
This constant has the NS_AVAILABLE_IOS(8_0) suffix. So I assumed the constant is only available when running on iOS8 and above.
When I set the deployment target in Xcode from 8.0 to 7.1 and hit 'Build & Run', to my surprise there was no error at all and the app ran on my iOS7.1 device without any problem. - Even while the code contained the constant that should only be available at >= iOS8.
So here are the questions that came to my mind at this point:
The NS_AVAILABLE_IOS(8_0) suffix in the header files does not determine the iOS version, but rather the SDK version from which on the marked API is available. - is that correct?
Does this mean we are able to use APIs added in the iOS8 SDK in apps that are compiled for iOS7.1, as long as we use the new SDK to build the app?
I'm particularly curious about the second question, because that would mean we can use cool new stuff like the UIVisualEffectView for apps that run on iOS < 8. Also, this would mean much less headache for example when maintaining CoreLocation functionality while following all the changes made to it (kCLAuthorizationStatusAuthorized -> kCLAuthorizationStatusAuthorizedWhenInUse, etc.), because we can simply maintain a single code base and do not have to #ifdef a lot.
Please tell me if my assumptions are correct and if not, please correct them in your answer.
Thank you!
It's important to realize that linking against the iOS 8 SDK with a deployment target of iOS 7 allows you to create an application that will run on both, but there will be differences in API availability.
When the application is run on iOS 7, iOS 8 APIs will be unavailable. At runtime, acccessing an iOS 8 API can cause a crash or other undesirable behavior. The recommended way to handle this is when using classes, methods, or constants that are marked as available only on iOS 8 or later, you must query for their availability at runtime.
In the case of new UIViewControllerContextTransitioning methods, you would query for the presence of those iOS 8 methods at runtime:
if ([transitioner respondsToSelector:#selector(viewForKey:)]){
// It's available, you're set to call it
} else {
// The method is not available, you will have to work around it.
}
Obviously, this can complicate things significantly for some applications. The application DeployMate can be very useful for finding API disparities in your code base. It will scan your project and tell you where you are using a method that is iOS 8 only.
Guidance for supporting different SDK and OS versions and capabilities is explained in more detail in the iOS 7 Tech Talk Architecting Modern Apps, Part 2. While the examples are for supporting iOS 6 and 7, the guidance here applies to supporting more than one OS or SDK, no matter what the version.

NS_ENUM, NS_OPTIONS, NSArray[dereferencing] not working XCode 4.6

I'm trying to compile the PSTCollectionView library using XCode 4.6, but for some reason, I'm getting a ton of compiler errors. They're all centered around the newer features of Objective-C.
A few examples:
However, the new array/dictionary/NSNumber macros are defined:
I'm using the Apple LLVM Compiler
I'm a bit stumped by this... any notions?
This is apparently an issue caused by using the wrong SDK. I was using the iOS 5.1 SDK, which does not allow the use of these handy new shortcuts that Apple added. When I change to the iOS 6.1 SDK, it no longer complains about that usage.
Apple lets you know in this article here.

Attempting to use Social.framework on ios 5.1.1 crashes my App

My app is getting an error message and crashes on the iOS 5.1 simulator because this iOS 5.1.1 doesn't support the "Social" framework.
Is there a way to solve this and use it on versions prior to iOS 6?
The Social Framework is an iOS 6 Only feature. It will NOT work on devices running iOS earlier than 6.0. You have two options. If your App is new you can require iOS 6 or greater.
If your App has been out there for a while and you need to support versions of iOS earlier than 6 you can test for the existence of the framework at run time with something like this:
if(NSClassFromString(#"SLComposeViewController") != nil) {
// The social Framework exists
else
// Social Framework does NOT exist.
NOTE IN RESPONSE TO YOUR COMMENT BELOW:
It is considered bad design to use the version number to check for the existence of a feature. The recommended approach is to check for the existence of the feature itself.
The code you mentioned in the comment is a perfect example of WHY you test for the feature and not the version. The floatValue of #"5.1.1" is 5.1 AND the floatValue of #"5.1.2" is also 5.1! If the feature your looking for is not in 5.1.1 but IS in 5.1.2 your code will NOT detect it and incorrectly assume the feature DOES NOT exist. Don't do this. Use the technique I outlined above.

Resources