Using new iOS 10 API in compiled framework under XCode 7 - ios

My company is developing an iOS SDK, which uses the new CallKit APIs. The SDK (.framework) is compiled with XCode 8 / SDK 10.0.
However, some of out customers are still using XCode 7 - When I try to integrate our SDK under a XCode 7 project, I got the following error :
ld: framework not found CallKit for architecture arm64
However, I put some macro directive into the SDK code, to provide a CoreTelephony fallback, but event with this trick, the project's target does not compile with the message above.
Here is the directive example :
#ifdef __IPHONE_10_0
#import CallKit;
#endif
Do you have a trick to use a SDK compiled with iOS 10 API working under XCode 7 ?
EDIT
Find a way to manage that. The idea is to lazy load CallKit (runtime). I had to call performSelector instead of calling directly methods.
Here is some code :
// Lazy load CallKit framework to keep compatibility for XCode 7 SDK integration
if ([[AppKit sharedInstance] systemVersion] >= kIosSystemVersion10) {
NSBundle *b = [NSBundle bundleWithPath:#"/System/Library/Frameworks/CallKit.framework"];
_isCallKitFrameworkLoaded = [b load];
}
if (_isCallKitFrameworkLoaded) {
SEL callObserverDelegate = NSSelectorFromString(#"setDelegate:queue:");
if ([_callObserver respondsToSelector:callObserverDelegate]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[_callObserver performSelector:callObserverDelegate withObject:self withObject:(__bridge id)(_callObserverQueue)];
#pragma clang diagnostic pop
}
} else {
// CoreTelephony fallback
}

CallKit is available from iOS 10 and later. Xcode 7 support upto iOS 9 only. If you need to use this framework, you need to update to latest Xcode(obviously Xcode8) which supports iOS 10.
So users who are having iOS 10 only can use this feature and not iOS 9.

Related

Unknown type name 'SKPaymentDiscount'. FBSDKCoreKit

I am facing an issue when building the Facebook sdk for iOS facebook-ios-sdk in my Swift 3 iOS application.
I have recently updated the FBSDKCorekit and FBSDKLoginkit pods I'm using in my iOS application from version 4.30.0 to 5.13.1
I am using XCode 9.3.1 targeting iOS 10.2. when building my application with XCode I get the following issue: Unknown type name 'SKPaymentDiscount'; did you mean 'SKProductDiscount'?
This error is raised when the compiler attempts to build the following file Core/FBSDKPaymentObserver.m. See the following segment.
...
#if !TARGET_OS_TV
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_4
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_12_1
// promotional offer starting from iOS 12.2
if (#available(iOS 12.2, *)) {
SKPaymentDiscount *paymentDiscount = transaction.payment.paymentDiscount;
if (paymentDiscount) {
NSArray<SKProductDiscount *> *discounts = product.discounts;
for (SKProductDiscount *discount in discounts) {
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial &&
[paymentDiscount.identifier isEqualToString:discount.identifier]) {
return YES;
}
}
}
}
#endif
...
As I understood after doing some research, SKPaymentDiscount was only introduced in iOS sdk 12.2 . Since I am using XCode 9.3.1 the latest available iOS SDK is 11.3 but the conditional compiler expression #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_12_1
should make sure the compiler does not build the previous code segment.
However that doesn't seem to be the case and I am getting the build error.
Unknown type name 'SKPaymentDiscount'; did you mean 'SKProductDiscount'?
I have tried installing XCode 10.0 which supports iOS sdk 12.2 but I got the same error. Please advise.
You should update to Xcode 11.3.1. It is the latest version currently as of Jan 2020.

Can I use "uppercaseString" in an app targeting 8.0? Is it safe pre iOS 8.3?

I'm using the built in string method uppercaseString, like this:
let capitalLetters = myString.uppercaseString
The documentation tells this for availability:
iOS (8.3 and later)
However, Xcode is not giving a compiler error, with the if #available recommendation, i.e:
if #available(iOS 8.3, *) {
} else {
}
My question is simple. Can I use this method in an app targeting 8.0? I cannot test it on a device with this version because I don't have one. And the simulator I have is 8.4.
From Apple's documentation:
var uppercaseString: String { get }
Available in iOS 2.0 and later.
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/index.html#//apple_ref/occ/instm/NSString/uppercaseString
Sometimes xcode shows you wrong availability versions (since swift came out). If sometimes you aren't sure about the availability - check it online.
PS: You can download simulators for which version you want

Was I supposed to get a warning [duplicate]

This question already has an answer here:
Why is the Xcode compiler not warning me about invalid methods for my Deployment Target?
(1 answer)
Closed 9 years ago.
In my code I use
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:dismissBlock];
The thing is my deployment target is set to: 5.0.
While base SDK is 6.1.
Was I not supposed to get a warning by XCode? (because I think the above method got introduced in iOS6).
Unfortunately no, Xcode doesn't check if you use symbols that are not available in your deployment SDK.
It only checks your code against the base SDK.
But you can use some third-party software for this, like DeployMate.
That being said, as others pointed it out, dismissViewControllerAnimated:completion: is available since iOS 5, so your code is safe.
But it's always a good idea to check for unavailable or deprecated APIs in your app, using something like DeployMate.
EDIT
Here's an answer to your comment:
If you deployment target is 5.0 and your base SDK 6.0, using a symbol available in the 6.0 SDK on an iOS 5 device will crash the application.
But Xcode won't warn about this when compiling, hence the need of some third-party software.
Once you identified the problematic symbol, using respondsToSelector: is the way to go, as it's better than simple version checking.
This way, you can have conditional code that will run with both SDK versions:
if( [ someObject respondsToSelector: #selector( someIOS6Method ) ] )
{ /* iOS 6 code */ }
else
{ /* iOS 5 code */ }
Only do this if you have detected SDK issues. Don't do this for everything.
According to UIVIewController class reference, this method is available from iOS 5.0 and higher.
Availability
Available in iOS 5.0 and later.
It is not ok to warn you. It doesn't have this warnining included in the default bundle of the SDK.

Conditionally Hide Code from the Compiler

So here's the problem. I'm set to release an update soon for iOS that will address some problems in iOS 7. In order to do this, I need to use some specific iOS 7 functions/types. I've made absolutely certain that iOS 7 code will only be executed on iOS 7 and fallback to different code for pre iOS 7. Of course, I'm not allowed to submit with the current Xcode beta, so I'm trying to compile with the current Xcode release. However, I can't seem to find a way to disable this particular warning:
Use of undeclared identifier '<Redacted>'.
Does anyone know of a way to disable this warning using a #pragma. I've tried a bunch of different ones including
-w, -Weverthing, -Wall
but nothing seems to work.
UPDATE
Answer: You can't, of course, because the compiler can't compile an identifier it knows nothing about. My solutions was to simply create a #define:
#define <redacted> 1
UPDATE 2
The answer below actually made it much easier. I had already created a #define Xcode5Code(code, alt) that allowed me to execute code blocks conditionally. By modifying it using the solution by #maddy:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
#define Xcode5Code(code, alt) code
#else
#define Xcode5Code(code, alt) alt
#endif
This allows me to to easily hide blocks of code from the compiler by using:
Xcode5Code({
//Code to be execute only with Xcode 5
}, {
//code to be executed in previous versions of Xcode
})
The main benefit of using the #define Xcode5Code is that Xcode will auto-complete it for you, which is a lot easier than using the full #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000, which Xcode won't auto-complete.
This won't actually distinguish between iOS 7 and pre iOS 7 devices. It only distinguishes what version of iOS the current Xcode can handle. To distinguish between iOS devices versions I use:
NSUInteger DeviceSystemMajorVersion(void) {
static NSUInteger _deviceSystemMajorVersion = -1;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] objectAtIndex:0] intValue];
});
return _deviceSystemMajorVersion;
}
The above is Apple's code, by the way. To dance around the NDA a little, I'll say that this helps with laying out a root controller's view, because that depends on both the version of Xcode you're using AND the version of iOS that's on the device. And if you're trying to manage beta's as well as production code, this can help a lot. Once you can submit apps with Xcode 5, the #define Xcode5Code will no longer be necessary.
If you want to compile your app with two difference versions of Xcode or two different Base SDK settings then you should use compiler directives:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 // iOS 7.0 supported
// iOS 7 code here
#else
// Pre-iOS 7 code here
#endif
Do not use this for runtime checks. This solution is only to be used when you must compile your code with two different versions. An example would be you have added iOS 7 code but you still need to compile the code with Xcode 4.6. Using the compile directives allows you to "hide" the iOS 7 code from the compiler using the older Base SDK.
See the "SDK Compatibility Guide" in the docs for more on this and proper runtime checks.

ios Facebook SDK Pragma, GCC error

I have to implement a Facebook sharing method... I watched the video, read a couple of tutors, etc...
1: I registered my app, downloaded the sdk, the samples are running fine
2: when i drag and drop the FacebookSDK.framework into my app (not a new app, it has custom frameworks), and include the #import into the desired class and the appdelegate, during the build, i keep getting the following error in FBRequest.h:
LLVM GCC 4.2 error
'#pragma' is not allowed here
LLVM GCC 4.2 error
instance variable '<unnamed>' has unknown size
LLVM GCC 4.2 error
expected `;' before 'NSError'
This is the problematic area
#interface FBRequest : NSObject {
#private
id<FBRequestDelegate> _delegate;
NSString* _url;
NSURLConnection* _connection;
NSMutableData* _responseText;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
FBRequestState _state;
#pragma GCC diagnostic pop
NSError* _error;
BOOL _sessionDidExpire;
id<FBGraphObject> _graphObject;
}
XCode 4.5, trying to run in ios 5.1 simulator and ios6 iPod 4. gen
Thanks
try switching to Apple LLVM compiler 4.1 instead of LLVM GCC 4.2 in your Project > Build Settings > Build Options > Compiler for C/C++/Objective-C
p.s. Choose "All" if you don't see "Compiler for C/C++/Objective-C" there.

Resources