How to convert CFStringRef to NSString? - cocoa

NSString *aNSString;
CFStringRef aCFString;
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding);
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL);
How can I get a new NSString from aCFString?

NSString and CFStringRef are "Toll free bridged", meaning that you can simply typecast between them.
For example:
CFStringRef aCFString = (CFStringRef)aNSString;
works perfectly and transparently. Likewise:
NSString *aNSString = (NSString *)aCFString;
The previous syntax was for MRC. If you're using ARC, the new casting syntax is as follows:
NSString *aNSString = (__bridge NSString *)aCFString;
works as well. The key thing to note is that CoreFoundation will often return objects with +1 reference counts, meaning that they need to be released (all CF[Type]Create format functions do this).
The nice thing is that in Cocoa you can safely use autorelease or release to free them up.

If you're using ARC in recent versions of Mac OS X/Objective C,
it's real easy:
NSString *happyString = (NSString *)CFBridgingRelease(sadString);
However, Xcode will happily warn you when you try to toll free bridge
CFString to NSString and offer to automatically wrap it in CFBridgingRelease(),
which you can accept and let it automatically insert the wrapper for you if you click the option.

They are equivalent, so you can just cast the CFStringRef:
NSString *aNSString = (NSString*)aCFString;
For more info, see Toll-Free Bridged Types.

Actually, you shouldn't use Cocoa retain, release, autorelease on Core Foundation objects in generality. If you're using Garbage Collection (only on Mac OS X for now), those retain, release, autorelease calls are all no-ops. Hence memory leaks.
From Apple http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html:
It is important to appreciate the asymmetry between Core Foundation and Cocoa—where retain, release, and autorelease are no-ops. If, for example, you have balanced a CFCreate… with release or autorelease, you will leak the object in a garbage collected environment:
NSString *myString = (NSString *)CFStringCreate...(...);
// do interesting things with myString...
[myString release]; // leaked in a garbage collected environment
Conversely, using CFRelease to release an object you have previously retained using retain will result in a reference count underflow error.
PS: can't seem to comment on Peter Hosey's answer - sorry for adding my own unnecessarily.

I'll add that not only can you go from CFString to NSString with only a type-cast, but it works the other way as well. You can drop the CFStringCreateWithCString message, which is one fewer thing you need to release later. (CF uses Create where Cocoa uses alloc, so either way, you would have needed to release it.)
The resulting code:
NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];

I was having an issue with ARC and the retain count of CFStrings. Using NilObjects answer with a slight tweak worked perfect for me. I just added retained eg.
CFStringRef cfstringRef = (__bridge_retained CFStringRef)aNsString;

You have to cast it:
CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;

Youcan use :With CFStringRef idc;
NSString *sId = [NSString stringWithFormat:#"%#", (NSString*)idc];

Related

Null passed to a callee that requires a non-null argument

I have been using this to convert a CIImage to NSData for ages:
NSData *data = [imageRep representationUsingType: NSPNGFileType
properties:nil];
Now on El Capitan I have this error on the second line:
Null passed to a callee that requires a non-null argument
I can solve that by using an empty array on the properties, like this:
NSData *data = [imageRep representationUsingType: NSPNGFileType
properties: #{}];
but I am suspecting that this can cause me problems in the future.
Is this the correct way to solve this problem?
Is this the correct way to solve this problem?
Yes.
There appear to be a few places in the API which accepted nil values rather than an empty collection even though it was not documented as valid. The non-nil annotations added by Apple to better support inter-working with Swift are just highlighting these.

Is the NSData a substring of the another NSData?

I have two NSData objects
NSData *toScan = /* initialized somehow with "Hello, this world." */;
NSData *toMatch = /* initialized somehow with "this" */;
What is the best way to know the toMatch bytes are the subset of toScan bytes?
I use C-functions for this purposes at this point: something like this
strstr([[toScan identifier] bytes], [[toMatch identifier] bytes]);
// returned bytes are null-terminated
but I think there is not the best way to use C-functions in object-oriented environment...
As of Snow Leopard and iOS 4.0, NSData has -rangeOfData:options:range: which should do what you want.
It's also pretty darn fast.
In a different question, I wrote an answer containing an NSData category with a rangeOfData: method:
Elegant Algorithm for Parsing Data Stream Into Record
That'll do what you're looking for.

I have a plist that is an array of dictionaries I need to save to documents directory is this code correct?

Is the code below correct for saving to disk?
// get the path to the "Documents" directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// get the path to our plist ("Documents/foo.plist")
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"foo.plist"];
// read or create plist
NSMutableDictionary *dict;
// check if our plist already exists in the Documents directory...
NSFileManager *fileManager = [NSFileManager defaultManager];
if ( [fileManager fileExistsAtPath:plistPath] ) {
// ...if it does, read it
NSLog(#"dict existed, reading %#", plistPath);
dict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
} else {
// ...if it doesn't, create it
NSLog(#"dict didn't exist, creating...");
dict = [NSMutableDictionary dictionaryWithCapacity:1];
No.
For one thing, it's missing a closing brace at the end, but maybe you just left that out when copying the code into the question.
For another, the code reads in a dictionary; it does not get an array (of anything) from anywhere, nor does it write anything (array or anything else) out.
It sounds like you copied the code from somewhere, hoping that it's what you need. Don't do that. Write your own code. Read code if you want, but only read it; do not just copy code into your program without understanding what it does, and don't rely on other people to tell you what code does.
In order to be a programmer in any language or framework, you must be able to read code in that language/framework. Read the Objective-C Programming Language and read the Cocoa Fundamentals Guide; once you know the concepts those guides teach, all that remains is to practice reading code.
You must also, obviously, be able to write code in the target language/framework. Copying other people's code is not a substitute. At best, you will end up with a shoddy program that is flaky or just doesn't work; at worst (if you're “programming” as a contractor or employee), you will be guilty of plagiarism.

Build and Analyze tool Cocoa Xcode

I tried Build and Analyze tool of Xcode very first time today.
and found some thing in this function
Please check the image:
-(IBAction)completeSessionButAct:(id)sender{
NSDictionary *tempDic = [[NSDictionary alloc] initWithObjectsAndKeys:[self view],#"mainview",
congratulationScreen,#"screen",
congScreenLabel,#"cong_screen_label",
congScrStatusLabel,#"cong_scr_status_label",
[sender superview],#"last_screen",nil];
[functionality completeSession:tempDic];
}
this function start from line 64 and end at 71
Can Any one explain me the memory leakage in this function.
The text as displayed in the image seems pretty clear to me: You are creating an object that you own (new, alloc, copy, retain [NARC] does that); but you never rescind ownership.
Try using +[NSDictionary dictionaryWithObjectsAndKeys:] instead.

Cocoa: Element count of property list without building dictionary?

What is the best way to count the number of entries in a property list?
I currently build a dictionary from the plist entries (*) and then use the dictionary's count:
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:myPlistPath];
NSDictionary *myPlistDict = (NSDictionary *) [NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
NSLog(#"There are %d entries in the plist.", [myPlistDict count]);
This strikes me as unnecessarily "heavy", but I was not able to find a more efficient solution. Any ideas?
(*) targeting 10.5 and therefore using the deprecated +propertyListFromData:… class method.
Well... if you're converting to XML anyway, you could use NSXMLNode's childCount method. The documentation does suggest that it's more efficient than calling [children count], but the creation of the NSXMLNode might make this just as bad (or even worse than) the NSDictionary method.
Have you profiled? Are you working with particularly large plists? Are you requesting this count often? I say: use NSDictionary, cache the value if you request it often, and move on unless this is unacceptably slow. (Yeah, it looks ugly right now, but there are bigger things to worry about.)

Resources