'name' is unavailable: not available on iOS - XCode11 - ios

After upgrading from XCode 10.0 to 11
I am getting the error 'name' is unavailable: not available on iOS
This is during Build for Swift 4.2 on XCode 11.0 and 11.1 , I can still build using XCode 10
This is happening in the code of one of the Objective C external libraries we have been using through Cocopods.
return [(NSNumber *)[table[state] objectForKey:[rule name]] unsignedIntegerValue];
I can work around the issue by renaming the variable name to ruleName , but I would rather not do this.
Why is Xcode objecting to a variable name of name? Is this an Xcode but or is it something I can fix in the build settings
Edit
The specific pod is NUI 0.5.5
In module NUIPShiftReduceGotoTable.m
- (NSUInteger)gotoForState:(NSUInteger)state rule:(NUIPRule *)rule
{
return [(NSNumber *)[table[state] objectForKey:[rule name]] unsignedIntegerValue];
}

Apple made a change that can break previously compiling code in Xcode 11.0/11.1. Previously the compiler would be fine with passing the 'name' message to an object that it didn't know the type of. This can happen for many reasons in the weakly typed Objective-C world.
Currently in Xcode 11.1 you can do.
id x = nil;
[x name];
And this will compile, no problem. But:
NSObject *x = nil
[x name];
won't compile due to the compiler identifying the most likely selector being the API_UNAVAILABLE one in NSLayoutAnchor.h (maybe).
If the compiler had more information it can map the correct selector. This might be as simple as including the header for whatever has name property in the .m file that is failing.
My guess is something like in NUIPShiftReduceGotoTable.m you add a line
#import"NUIPRule.h"

Related

What is accomplished by checking the address of a constant like SKStoreProductParameterAffiliateToken?

I have this code from a library I am using.
#ifdef __IPHONE_8_0
if (&SKStoreProductParameterAffiliateToken) {
if (self.affiliateToken) {
[appParameters setObject:self.affiliateToken forKey:SKStoreProductParameterAffiliateToken];
if (self.campaignToken) {
[appParameters setObject:self.campaignToken forKey:SKStoreProductParameterCampaignToken];
}
}
}
#endif
Xcode is saying that the first line will always evaluate to be true but what is this line doing exactly? I never saw a if with & and a constant in that way.
SKStoreProductParameterAffiliateToken is defined as
SK_EXTERN NSString * const SKStoreProductParameterAffiliateToken NS_AVAILABLE_IOS(8_0);
What is the developer trying to check, the address of a constant? Is he trying to check if the version of iOS has this constant defined and by doing that, he is trying to check the instruction inside the if should run? But he already has ifdef __IPHONE_8_0... (??!!)
I don't get it.
Anyway I am compiling for iOS 9.3, so I can delete the if and the ifdef, right?
It is a check to see if a weak-linked symbol is available. If the library/framework containing the symbol has been weakly linked and is not available its address will evaluate to NULL and the if condition will be false.
See Using Weakly Linked Methods, Functions, and Symbols in Apple's Using SDK-Based Development for full details.
#ifdef __IPHONE_8_0 checks if Xcode should compile code inside. Ohterwise older version of Xcode will show an error about unknown variable SKStoreProductParameterAffiliateToken.
But when using newer Xcode version (with iOS SDK 8+), we may still can set a lower minimum target for our project. In this case to avoid crash on devices with lower than iOS 8 version we should check first if variable, class, method or function exists.
In your case, we are checking if pointer to SKStoreProductParameterAffiliateToken is not NULL, which means app is currently running at least on iOS 8.

NSAttributedStringKey.attachment versus NSAttachmentAttributeName

I'm having problems with NSAttributedStringKey.attachment versus NSAttachmentAttributeName. Here's the relevant code:
var key: Any?
if #available(iOS 11, *) {
key = NSAttributedStringKey.attachment
}
else {
key = NSAttachmentAttributeName
}
One of two things are happening. In the actual place where I'm trying to use this code (a Cococapod of my own design, with a deployment target of iOS 8 and now building with Xcode 9), I get an error:
Type 'NSAttributedStringKey' (aka 'NSString') has no member 'attachment'
Or, if I just make a new example project and set the deployment target at iOS 8, I get:
'NSAttachmentAttributeName' has been renamed to 'NSAttributedStringKey.attachment'
This is not the behavior I'd expect with #available. Thoughts?
This String vs struct difference is between Swift 3 (uses Strings such as NSAttachmentAttributeName) and Swift 4 (uses struct static attributes such as NSAttributedStringKey.attachment), not between iOS <11 and iOS >=11. For instance, you can use NSAttributedStringKey.attachment and similar in any supporting version of iOS (e.g. .attachment is available since iOS 7) within a Swift 4 project. #available doesn't apply because it's a Swift language version difference rather than an OS version difference.
Ensure your pod is set to the correct Swift version and it should then work as expected. You can tell CocoaPods that by adding a .swift-version file at the top of your project:
$ echo 4.0 >.swift-version
This magical version file is mentioned in passing in a CocoaPods blog post from last year: http://blog.cocoapods.org/CocoaPods-1.1.0/

Swift App Extension: instance method count is unavailable

I just create my first app extension using XCode 7.1. One code file containing the code below is shared with both targets:
var str = "";
var l = str.count; //Compile error for extension target App: count is unavailable: There is no ...
The reason for this compile error seams to be that App extension compiles with swift 1.2 while the container target compiles with swift 2.0.
One solution would be importing the content App into the extension App doesn't appear to be a good solution from what i read about it. Sharing the code between targets can be difficult if both are not compiled using the same compiler.
I just run through all target settings and didn't find nothing that could be changed.
Can't find any post about this problem, witch is not so uncommon, so it is must likely i am interpreting something in a wrong way.
The only solution i can think of is using NSString instead of String but that is just an workaround for one class type. More problems of this kind will emerge in the future.
In Swift 2 it's
str.characters.count
Use str.characters.count to get String length in Swift 2

Using new features while supporting older iOS versions

I am developing an app using SDK 8.1, Apple LLVM 6.0 and Xcode 6.1.1. The deployment target is 6.0. I'm using NSOperationQueue and I want to use QoS whenever it's available.
The code I'm using is:
if ([self.operationQueue respondsToSelector:#selector(setQualityOfService:)]
&& (&NSOperationQualityOfServiceUserInitiated)) {
[self.operationQueue performSelector:#selector(setQualityOfService:) withObject: NSOperationQualityOfServiceUserInitiated];
} else {
//Other stuff not related to the scope of this question
}
The error I get is:
Use of undeclared identifier 'NSOperationQualityOfServiceUserInitiated'
I added the if (&NSOperationQualityOfServiceUserInitiated) part to check if this constant exists. This code worked with older versions of Xcode/Obj-C Compiler.
I am able to use selectors with performSelectorWithIdentifier but what about constants that do not have a defined value in the docs? The value of this constant is set by NSQualityOfServiceUserInitiated but there is no definition for this value that can be hardcoded.
How do I fix that?
There are several things wrong with the code.
NSOperationQualityOfServiceUserInitiated is a native type (NSInteger) so you can't use it the way that you are in either line.
The qualityOfService is a property of type NSQualityOfService. Your attempt to pass an argument to the qualityOfService method (getter method) makes no sense. If you are trying to set the quality of service, you need to call the setter but you can't use performSelector.
You want:
if ([self.operationQueue respondsToSelector:#selector(qualityOfService)]) {
self.operationQueue.qualityOfService = NSOperationQualityOfServiceUserInitiated;
} else {
//Other stuff not related to the scope of this question
}
This code will compile fine as long as your Base SDK is iOS 8.0 or later. The Deployment Target doesn't matter.
If you also want to build this code with Xcode 5 or earlier (a Base SDK of iOS 7 or earlier) then you need to wrap the code with the proper compiler directives to check for the Base SDK.

RestKit installation to XCode gives multiple errors

I am using a project without ARC. I am trying to install RestKit on to the project. I tried following instructions given in the following links:
https://github.com/RestKit/RestKit/blob/master/README.md
http://www.raywenderlich.com/13097/intro-to-restkit-tutorial
But I am getting following errors
The errors happen on following lines:
1. Unexpected # in the program:
NSArray *attributeNames = [userInfoValue isKindOfClass:[NSArray class]] ? userInfoValue : #[ userInfoValue ];
Is this a valid Obj C syntax first of all.
Array subscript is not an integer
NSAttributeDescription *attribute = [entity attributesByName][attributeName];
attributeName is a CFStringRef
Has any one faced these issues. Please inform me the fix.
This is do to the use of Objective-C literal subscript access to the attribute property.
What version of Xcode are you building against and with what base SDK? Under Xcode 4.5.2 with a base SDK of 6.0 it compiles without an issue.

Resources