NSString method deprecated, but replacement not there? - objective-c

I am (re)building a project written in objective c in XCode 3.2.6 64 bit under a 10.6.8 VM based on the 10.5 SDK (for compatibility with 10.5 and up - so this is a given.) The build is up and working. But. I'm trying to address the last four warnings in this project. They're all the same warning. Specifically...
In the project, there are four ASCII c strings that need to be converted to four corresponding instances of objective c's NSString. There are four essentially identical cases. This is how it's being done:
[tf setStringValue: [NSString stringWithCString: strg]]
This works, but results in (four) warnings that stringWithCString is deprecated and looking further, I find that's been true since about 10.4. So I'd expect the 10.5 SDK to have whatever replacement is required.
Looking at the docs, the suggested replacement is:
[tf setStringValue: [NSString stringWithCString:NSASCIIStringEncoding: strg]]
However, when this is used, XCode says:
'NSString' may not respond to '+stringWithCString::'
Which probably means it really won't respond. And besides, even if it does, replacing one warning with another.... yech.
Anyone know what I should be doing differently? I realize that this is old, old stuff, but surely Back In The Day people didn't just let these warnings clutter up their builds? Have I just got some kind of syntax error here, or... ?

[NSString stringWithCString:NSASCIIStringEncoding: strg]
The correct syntax for calling this method is:
[NSString stringWithCString:strg encoding:NSASCIIStringEncoding]

Related

What does this Objective-C code snippet mean, and what document details it?

Ok, so I've done searches in Xcode, on Apple's developer's site, and on google, and have even downloaded and searched pdf versions of the Key-Value Coding Programming Guide and Collections Programming Topics, but I cannot find this syntax listed anywhere. What does the second line of the following snippet do, and where can I find the details on it?
NSMutableDictionary *change = [NSMutableDictionary new];
change[#(someVariable)] = #(someOtherVariable);
I don't know if I'm having a brain fart, or if I've actually never seen this before, but it really bugs me that I can't find documentation for it.
This is the new syntax introduced in Objective C relatively recently. It is documented at this link.
Scroll down to Object Subscripting syntax for an explanation:
Objective-C object pointer values can now be used with C’s subscripting operator.
Your code fragment translates as
[change setObject:#(someOtherVariable) forKeyedSubscript:#(someVariable)];
To support the new syntax described there, the Objective-C #-expression grammar has been introduced. The #-expression is explained at the bottom of the document.
http://clang.llvm.org/docs/ObjectiveCLiterals.html
Check out "examples" about half way through the doc
There are actually two things going on here:
Dictionary (and array) subscripting
change[key]
This is a new syntactic sugar for
[change objectForKey:key]
Or, if used as an lvalue, it is syntactic sugar for
[change setObject:value forKey:key]
For what's really going on here (objectForKeyedSubscript: and setObject:forKeyedSubscript:) see http://www.apeth.com/iOSBook/ch10.html#_nsdictionary_and_nsmutabledictionary
Number literals
#(someVariable)
This is a new compiler directive, equivalent to:
[NSNumber numberWithInt: someVariable]
Except that in fact it will use numberWithInt:, numberWithFloat:, or whatever is appropriate based on the type of someVariable.
Again, see http://www.apeth.com/iOSBook/ch10.html#_nsnumber

Reset/fix Xcode 4.5 code completion

One of the new "features" in Xcode 4.5 was supposed to be vastly improved code completion. It was supposed to learn what you type regularly and provide these more frequently as options for code completion.
However, for me this isn't working at all.
One of the famously bad code completion words is NSString.
When I type it I get...
NS - NSAddedPersistentStoresKey
NSS - NSSaveChangesRequest
NSSt - NSStoreModelVersionHashesKey
NSStr - NSStream
NSStri - NSStrikethroughStyleAttributeName
NSStrin - NSString
I have never used any of the other suggestions given and most of them I'm not actually sure what they are. I use NSString many times a day, why wasn't it suggested first? In fact, apart from NSSet I don't think I've ever used another class that begins with NSS.
Also, when looking for NSLog() which used to get suggested when I typed NSL I now get...
NS - NSAddedPersistentStoresKey
NSL - NSLayoutAttribute
NSLo - NSLoadedClasses
NSLog - NSLog(<#id, ...#>)
Again, never heard of the others.
Is there any way to fix this so that I get the functionality that Apple says I should be getting?
Thanks for any help.
OK, I deleted the UserInfo folder from ~/Library/Developer/Xcode/ and it seems to have fixed it.

Warning: Unimplemented Selector localizedCaseInsensitiveCompare

I'm getting the subject warning on the following line:
NSSortDescriptor * sort = [ [NSSortDescriptor alloc] initWithKey:#"name"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:) ];
And I didn't always get that warning. That is, the warning just started to appear recently, possibly due to a change in compilation settings. I don't see a typo, here. This looks (to me) just like code I've seen in many examples. I'm not seeing a run time exception. But I don't like warnings. Anyone seen this? Any idea what's triggering it?
Did you turn on -Wselector? (Also called "Multiple Definition Types for Selector.") This warning is incompatible with Foundation and you should not turn it on. It exists because it does make sense in "pure" Objective-C. Just not in any Objective-C you'd ever be likely to write (i.e. anything that uses Cocoa).
The warning you want is -Wundeclared-selector, also called "Undeclared Selector."
It's somewhat dated, but I've compiled a complete list of GCC warnings and whether to turn them on or off in my Shared.xcconfig file. There is also a very helpful bestiary compiled by Jean-David Gadina that is a bit more up-to-date.

NSDate initWithString

After updating Xcode to version 4.2 I received the following warning in my current project:
warning: 'NSDate' may not respond to 'initWithString:'
What must I do? :)
This method is in the documentation only noted at the Mac OSX page, not the iOS.
Why Apple has different versions is unclear to me, but they luckily respond the same.
Because the class reference for iOS says there is no such method for iOS NSDate, you get the warning.
Your code, however, will respond perfectly fine.
To silence the warning, you should indeed use NSDateFormatter.
Regards,
Jacco
You should use NSDateFormatter to get an NSDate object from a string. This will give you more flexibility with the format of the input string.
NSDateFormatter Reference
Read the changes at this website http://developer.apple.com/library/ios/#releasenotes/General/iOS42APIDiffs/index.html
Sometimes they change little syntax things and make newer and better ways of doing things.

How to conditionally use a new Cocoa API

In 10.6 Apple added +[NSPropertyListSerialization dataWithPropertyList:format:options:error:] and labeled the older +[NSPropertyListSerialization dataFromPropertyList:format:errorDescription:] as obsolete and soon to be deprecated. One way to use the newer call on 10.6 and above, and still run on earlier OS releases, would be something like this:
if ([NSPropertyListSerialization respondsToSelector:#selector(dataWithPropertyList:format:options:error:)]) {
data = [NSPropertyListSerialization dataWithPropertyList:dict
format:NSPropertyListXMLFormat_v1_0
options:0
error:&err];
} else {
data = [NSPropertyListSerialization dataFromPropertyList:dict
format:NSPropertyListXMLFormat_v1_0
errorDescription:&errorDescription];
}
Built against the 10.4 SDK (for compatibility with that release), this results in: warning: 'NSPropertyListSerialization' may not respond to '+dataWithPropertyList:format:options:error:' And, worse, since the compiler does not know about this selector, it may pass the arguments incorrectly.
Is NSInvocation the approved/best way to call new APIs that, as far as the SDK is concerned, don't yet exist?
IIRC, you want to use the 10.6 SDK and set your deployment target (MACOSX_DEPLOYMENT_TARGET) to 10.4 so the 10.5/10.6 symbols are weak-linked. Then you can use the respondsToSelector: stuff and not get warnings.
Make sure you're checking that the object can respond to the selector, of course, or you will crash on 10.4/10.5.
One other way of doing things is to declare the missing method yourself as a category of the class in question. This will get the compiler to stop complaining about not finding the method, though of course you'll still need the runtime check you're already doing to avoid actually calling the method. You might also want to wrap such a declaration using availability macros, so that it will be ignored once you do move up to using the 10.5/10.6 SDK and you won't get a different compiler complaint down the line. That would look something like this:
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4 //ignore when compiling with the 10.5 SDK or higher
#interface NSPropertyListSerialization(MissingMethods)
+ (NSData *)dataWithPropertyList:(id)plist format:(NSPropertyListFormat)format options:(NSPropertyListWriteOptions)opt error:(NSError **)error;
#end
#endif