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

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.

Related

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.

Cannot Archive Array of Values Representing CGPoints

I have converted CGPoint To NSValue and put all the resulting values in q NSArray but when I use [NSKeyedArchiver archiveRootObject:ArrayName toFile:PointArrayFile]; it gives me error.
So what's the problem?
You don't say what problem you're seeing but in general you're probably better off using NSStringFromCGPoint and CFPointFromString to store and retrieve the points.

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.)

Read input from a cocoa/foundation tool console?

I wonder if Objective-C/Foundation has any special commands for reading user input from the console. Since it has NSLog for output maybe there is something else I could use instead of the scanf command.
I need to read some numbers (user input) into my tool. What is the best way to get these input in types like double or int? And how do I get user input into an NSString?
I was bored earlier and came across this issue of 'use scanf'. since I wanted to see if I could do it without dropping into c, the following came up:
NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];
while (1)
{
NSData* data = [input availableData];
if(data != nil)
{
NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
I'm sure somebody could optimize this and make it nicer (this was used for a really simple PoC CLI tool)
The only real Cocoa support for input is NSFileHandle's fileHandleWithStandardInput. It isn't really more useful than scanf() if you ask me. But for getting input into specific types, well, that's pretty much NSFormatter's thing. There are already a lot of predefined formatter types for standard things, and you can make a custom formatter if you have more specialized needs. So if you need something a little more than scanf(), just read in the data (either as bytes with scanf() or data with NSFileHandle) and make an NSString from it and you can format it to your heart's content.
Nothing like scanf (which is a good thing). You can slurp data from stdin using NSFileHandle; for interactive input, fgets is better. You'll then want to use either strtol/strtoul/strtod, NSScanner, or NSNumberFormatter to convert the input to numeric types.

How to convert CFStringRef to NSString?

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];

Resources