Get warning when using representationUsingType:NSPNGFileType properties:nil [duplicate] - objective-c-blocks

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

Objective-c - NSData initWithContentsOfFile vs. dataWithContentsOfFile

What is the difference between these two objective-c statements?
NSData *documentBytes = [NSData dataWithContentsOfFile:filePath];
versus this:
NSData *documentBytes = [NSData initWithContentsOfFile:filePath];
From Apple's NSData Class Reference page, it states the following about each
dataWithContentsOfFile - Creates and returns a data object by reading every byte from the file specified by a given path.
initWithContentsOfFile - Returns a data object initialized by reading into it the data from the file specified by a given path.
To me, these seem functionally equivalent but I highly doubt they do the same thing in all cases, right?
Thanks in advance...
-Ergin
When you use init, you always have to use alloc, like so:
NSData *documentBytes = [[NSData alloc] initWithContentsOfFile:filePath];
This returns an NSData object with a retain count of 1, you now own the reference and are responsible for releasing it.
When using dataWithContentsOfFile
NSData *documentBytes = [NSData dataWithContentsOfFile:filePath];
You get back an autoreleased NSData object. You can use it and forget about it, the autorelease pool will take care of it. If you want to store it, you have to retain it.
Of course, when you are using ARC, you can forget about all of this ;-), the methods are essentially the same.
The second
NSData *documentBytes = [NSData initWithContentsOfFile:filePath];
Will not compile you will need to alloc it first, will look something like:
NSData *documentBytes = [[NSData alloc] initWithContentsOfFile:filePath];
But one or another will work the same, in the end you will have an NSData that has the contet of the file. The first one is a shortcut.
So about your doubt:
The first one you do not need to alloc the object first, the method will return the object for you, if you are not using ARC (I do not think so), the first one will return an object that the system will take care.
The second one you will need to alloc the object first, the method only initialize your object, and if you are not using ARC you will need to take care to release it.

Instance Message Error in Objective-C, What does this mean? And why is it happening?

I get the below error hor no apparent reason, I would try to fix it myself but I can't understand what it means. Does anyone else understand it? Here is the error and below it is the code.
Error: Receiver Type 'NSdata' for instance message does not declare a method with selector type 'EncryptAES:'
I have added a comment to the line with the error on it:
//Change the Input String to Data
NSData *objNSData = [NSData dataWithData:[Input dataUsingEncoding: NSUTF8StringEncoding]];
//Encrypt the Data
[objNSData EncryptAES:Keyword.text]; //Error appears here
NSString *InputString = [[NSString alloc] initWithData:objNSData encoding:NSUTF8StringEncoding];
What does this mean, why is it happening and what can I do to fix it?
And, what is an instance message?
The problem here is that NSData does not respond to the EncryptAES: selector. You can only invoke selectors that exist on the class. With the Objective-C runtime's loose typing, you can also invoke a selector on a class that does not respond to said selector, as long as the selector appears in the implementation of at least one other class that the compiler is working with.
All standard NSData methods can be found on the NSData Class Reference. Apple has sample code for encryption, but it is not built-in to NSData.
My guess is that you're trying to use the AESEncrypt "category" for NSData, but you don't actually have the category installed in your project.

NSSet with NSStrings containstObject not return YES when it should

I'm loading a dictionary (list of word, not the class) into a NSSet as NSStrings. I then repeatedly send this set the message -containsObject:someNSString. But it always returns false. I wrote some code to test it:
NSLog(#"Random from dictionary: %#", [dictionary anyObject]);
NSString *test = [NSString stringWithFormat:#"BEMIRED"];
NSLog(#"To match this word: %#", test);
if ([dictionary containsObject:test])
NSLog(#"YES!");
In the log I get the following:
Random from dictionary: BEMIRED
To match this word: BEMIRED
(I'm missing the "YES!")
When I try using CFShow(dictionary) I can see that it actually contains Strings and that everything. An example:
0 : <CFString 0xc3bd810 [0x1386400]>{contents = "BEMIRED"}
3 : <CFString 0xdf96ef0 [0x1386400]>{contents = "SUBJECTIFIED"}
Can anyone please help me here?
Thanks!
NSSet uses isEqual: to test for object equality, which NSString overrides to perform a string comparison as you would expect. The follow unit test passes:
- (void)testSetStrings
{
NSSet *set = [NSSet setWithObject:#"String 1"];
// I've used the UTF8 initializer to avoid any cleverness from reusing objects
NSString *string1 = [[[NSString alloc] initWithUTF8String:"String 1"] autorelease];
// Test the references/pointers are not the same
STAssertTrue([set anyObject] != string1, nil);
STAssertTrue([set containsObject:string1], nil);
}
We can see the two strings have different pointer values, but the set still returns YES for the containsObject: call.
So I would guess your strings are not in fact equal. I would check for hidden whitespace or other similar issues.
The -[NSSet containsObject:] seems to check for the pointer value only (the documentation is very lacking for that method), not for object equality. So you need to use -[NSSet member:] instead, which uses isEqual: to check whether an object that is considered to be equal is in your set.
if ([dictionary member:test])
NSLog(#"YES!");
Edit: Actually it seems that containsObject: does use isEqual: as well. They only seem to differ in what they return (containsObject: returns a BOOL while member: returns id). I'm letting this answer stay for documentation purposes.
Ok so I solved the problem and it had nothing to do with the containsObject method. As I commented i used Dave DeLongs DDFileReader found here: Dave DeLongs DDFileReader
So by using CFShow on the entire dictionary I noticed that every word had a new line at the end of it. So instead of the -readLine method i used the -readTrimmedLine (bot methods in above mentioned file reader). This solved the problem for me.
For future forum visitors I'd like to draw attention to the discussion DarkDust and zoul had about -containsObject and -member (both methods of NSSet) which it turns out both uses the -isEqual method.

Is there a method for adding one NSString for NSData?

I'm working on writing to a file one user input on a textField.
So far I have one NSFileManager which writes data to a file. Still, I have no way of putting the textField input inside a file.
Is there a way do add a string value to NSData so I can write it?
you can get NSData from NSString,
NSData *newData = [yourString dataUsingEncoding:NSUTF16StringEncoding];
use encoding that fits your case.
append the obtained data to existing NSData,
[existingData appendData:newData]
Note: "existingData" should be an instance of NSMutableData.
Use below code as your reference.
NSString* myString = #"Is there a method for adding one NSString for NSData";
NSData* myData= [myString dataUsingEncoding:NSUTF8StringEncoding];

NSScanner & Array Loops

I am trying to use NSScanner is an NSArray enumeration loop. This however fails:
-[NSXMLElement length]: unrecognized selector sent to instance 0x280da30
No, I am not calling length anywhere. It seems like the value of found gets changed before the scanner completes, hence making it blank, causing the length error.
If I remove the loop and hardcode the string (i don't want that, it's just a test) the code below works. (excluding the enumeration of course)
It never gets as far as calling the NSLogs either...
Here's my code:
for (NSString*found in arr)
{
NSLog(#"Found %#",found);
NSString*search = [NSString stringWithString:found];
NSString *separatorString = #"\"";
NSString *container = nil;
NSScanner *aScanner = [NSScanner scannerWithString:search];
[aScanner setScanLocation:0];
[aScanner scanUpToString:#"src=\"" intoString:nil];
[aScanner scanString:#"src=\"" intoString:nil];
[aScanner scanUpToString:separatorString intoString:&container];
NSLog(#"scanned");
NSLog(#"%#",container);
NSImage*previewImage = [[NSImage alloc] initWithContentsOfFile:[relativeDir stringByAppendingPathComponent:container]];
[preview setImage:previewImage];
[previewImage release];
progressed = progressed + 1;
[convertProgress setDoubleValue:[convertProgress doubleValue] + progressed];
}
How can I get this to work?
Edit:
Here's the input:
NSXMLDocument*doc = [[NSXMLDocument alloc] initWithData:[NSData dataWithContentsOfFile:webPath] options:NSXMLDocumentTidyHTML error:nil];
NSArray*arr = [doc nodesForXPath:#"//img[#src]" error:nil];
From the documentation:
The nodesForXPath:error: method
returns an array of NSXMLNode objects
Your array is not full of strings. It is full of various NSXML* objects. They aren't garbage. This is exactly how it is supposed to work.
You may not be calling length, but stringWithString: is probably calling length to figure out how much space to allocate in the new string.
Conversion to a string can mean a lot of things. An XML node may be a standalone tag, it may be some inline CDATA, it may be a tag with various attributes. As well, an XML document is highly structured. It is rarely meaningful to walk through the contents of a document as a straight enumeration of tags/contents without applying some amount of structural meaning.
You are likely going to need to recurse or otherwise walk the tags and interpret their contents appropriately.
The first step would be to remove everything but that initial NSLog() and see what you got. Then figure out how to walk the tree of nodes. Then figure out how to parse 'em appropriately.
Are you sure that your arr contains NSString objects? The fact that NSXMLElement is throwing an error looks fishy to me.
Edit
Yep, looks like the docs say the array from nodesForXPath doesn't contain NSString objects, but NSXMLElement objects.
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSXMLNode_Class/Reference/Reference.html#//apple_ref/occ/instm/NSXMLNode/nodesForXPath:error: