I'm using FastttCamera as a wrapper to AVFoundation for taking, processing and displaying a picture. Here's my code (a FastttCamera delegate method) in which I cast (FastttCapturedImage *) to (UIImage *):
- (void)cameraController:(FastttCamera *)cameraController didFinishScalingCapturedImage:(FastttCapturedImage *)capturedImage
{
//Use the captured image's data--note that the FastttCapturedImage is cast to a UIImage
NSData *pngData = UIImagePNGRepresentation((UIImage *)capturedImage);
//Save the image, and add the path to this transaction's picPath attribute
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
int timestamp = [[NSDate date] timeIntervalSince1970];
NSString *timeTag = [NSString stringWithFormat:#"%d",timestamp];
NSString *filePath = [documentsPath stringByAppendingString:timeTag]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
self.thisTransaction.picPath = filePath;
[self.viewFinder setImage:(UIImage *)capturedImage];
}
However, I'm getting a SIGABRT at the line:
NSData *pngData = UIImagePNGRepresentation((UIImage *)capturedImage);
with this console readout:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FastttCapturedImage CGImage]: unrecognized selector sent to instance 0x17e2a100'
I'm confused by the reference to CGImage. Is it a problem with my typecast? There was no complaint on build. Can someone please set me straight?
Read the docs for FastttCapturedImage. It's not a UIImage so you can't just cast it like that. Use the provided property to get the UIImage.
Change the problematic line to:
NSData *pngData = UIImagePNGRepresentation(capturedImage.fullImage);
You have the same problem later:
[self.viewFinder setImage:capturedImage.fullImage];
BTW - you didn't get a problem while compiling because a cast is a way to tell the compiler "trust me, it's really what I'm telling you it is". The problem here is you were wrong, it's not really what you claimed it was. :)
Related
I'm using FastttCamera as a wrapper on AVFoundation in order to implement a camera in my app. Things appear to work fine until I try to save a captured image with the following code:
- (void)cameraController:(FastttCamera *)cameraController didFinishScalingCapturedImage:(FastttCapturedImage *)capturedImage
{
//Use the image's data that is received
pngData = UIImagePNGRepresentation(capturedImage.scaledImage);
NSLog(#"1 The size of pngData should be %lu",(unsigned long)pngData.length);
//Save the image someplace, and add the path to this transaction's picPath attribute
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
int timestamp = [[NSDate date] timeIntervalSince1970];
NSString *timeTag = [NSString stringWithFormat:#"%d",timestamp];
filePath = [documentsPath stringByAppendingString:timeTag]; //Add the file name
NSLog(#"The picture was saved at %#",filePath);
[self.imageWell setImage:capturedImage.scaledImage];
}
and
...
[pngData writeToFile:filePath atomically:YES]; //Write the file
NSLog(#"The pngData is written to file at %#",filePath);
NSLog(#"2 The size of this file should be %lu",(unsigned long)pngData.length);
self.thisTransaction.picPath = filePath;
...
I try to retrieve the picture later for use in a tableview cell, but nothing shows up. So I started trying to track where things go wrong, and apparently the data is not actually being written to the file specified by the file path. I'm getting the following console readouts from strategically placed NSLogs:
The pngData is written to file at /var/mobile/Containers/Data/Application/114FC402-83E0-4D15-B1E0-68E09DAB34DC/Documents1431292149
The size of this file should be 213633
and this return from the file at the file path:
The size of fileSizeFromFilePath is 0
I've looked at quite a few SO questions, but haven't been able to figure it out. Can someone please show me where I'm going wrong?
The pngData is written to a incorrect path /path/to/sandbox/Documents1431292149 which is not exist.
You should replace
filePath = [documentsPath stringByAppendingString:timeTag];
with
filePath = [documentsPath stringByAppendingPathComponent:timeTag];
I am using this to save a UIImage as a PNG
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSTimeInterval timeInMiliseconds = [[NSDate date] timeIntervalSince1970];
NSString *generatedString = [NSString stringWithFormat:#"background%f.png", timeInMiliseconds];
NSString *pngPath = [documentsDirectory stringByAppendingPathComponent:generatedString];
[UIImagePNGRepresentation(customBackground) writeToFile:pngPath atomically:YES];
I am saving pngPath into a plist from above then using the string in this:
UIImage *image = [UIImage imageWithContentsOfFile:string];
as string, the string shows up right and I can see the image file at the exact location it shows.
Now the strange part is as long as I don't close the app the method works fine, but if I close and reopen the app the UIImage file just stays nil. Any thoughts?
I am an idiot...
The string saved and retrieved was missing a "/" between the Documents and file name. Added it in and it works. Now I'm curious how it ever worked when app never closed. Thanks for the help guys. :)
This was working for me yesterday morning and now it doesn't. So, I suspect something else changed to cause it...but I can't find the change. I've spent hours reverting my code back almost a week and still it's not working (and I know it was working yesterday morning). So, I'm hoping that in posting this specific issue (a symptom?) some ideas will surface that I can evaluate. Thanks.
I download images as they're needed:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *targetFile = [NSString stringWithFormat:#"%#/%#.%#", documentDirectory, imageName, imageType];
// only download those where an image exists
if(![imageType isEqualToString:#""])
{
// only download the file if there is not already a local copy.
if([filemgr fileExistsAtPath:targetFile] == NO)
{
NSMutableData *imageData = [[NSMutableData alloc] initWithLength:0];
[imageData appendData:data];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *thumbNailFilename = [NSString stringWithFormat:#"%#.%#", imageName, imageType];
NSString *thumbNailAppFile = [documentsDirectory stringByAppendingPathComponent:thumbNailFilename];
}
}
Then display them:
NSString *imageFullName = [NSString stringWithFormat:#"%#%#", [greetingObject valueForKey:#"gid"], [greetingObject valueForKey:#"itp"]];
NSString *fullImagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageFullName];
UIImage *greetingImage = [UIImage imageWithContentsOfFile:fullImagePath];
self.greetingImage.image = greetingImage;
The variables "imageFullName" and "fullImagePath" are populated with the correct data and the image files are present on the simulator in the specified directory. Yet, "greetingImage" equals nil.
Here's what I get for "fullImagePath": /Users/Steve2/Library/Application Support/iPhone Simulator/7.1/Applications/8C9F8417-F6E2-4B38-92B3-82A88477CB7F/Documents/165.jpg
Here are the image files:
I have also tried variations using initWithContentsOfFile and dataWithContentsOfFile and get the same result. The greetingImage variable is nil.
I appreciate your ideas. I've even reinstalled Xcode in hopes that something got corrupted. No dice.
Added: One thing I just thought of... I did add the SystemConfiguration.framework to the project yesterday for an unrelated feature. It's currently at the top of the Linked Frameworks and Libraries list. I have no experience working with this. Could it be causing the problem?
Thanks.
Your code looks correct.
I would check that the images themselves are still okay. Looking at the screenshot you posted Finder isn't showing previews of the images which it should do with a valid JPEG. You say that the images are being downloaded so I suspect that they are being corrupted somehow on the way down.
EDIT:
Didn't notice that you were using initWithContentsOfFile. Since you are saving the files as NSData objects you will need to load them into memory as NSData objects and then init a UIImage with the data object, like so:
NSData *imageData = [NSData dataWithContentsOfFile:filePath];
[UIImage imageWithData:imageData];
I am trying to save my game data. I began with this tutorial from Ray: How to Save your Game’s Data: Part 1/2
Everything works fine except -(void)save;
-(void)save
{
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
}
When I called this method I get this;
-[__NSCFArray getFileSystemRepresentation:maxLength:]: unrecognized selector sent to instance 0x1663dcc0
2014-07-14 18:42:15.029 App[3629:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray getFileSystemRepresentation:maxLength:]: unrecognized selector sent to instance 0x1663dcc0'
Or this:
exc_bad_access code=1 address=0xc or exc_bad_access code=1 address=0x7000000c or exc_bad_access code=1 address=0x1000000c
on this line:
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
How can I fix this? Source code from tutorial works fine. But in my game its crashed.
UPDATE:
In Ray's source code Objective C ARC: YES. But then I use ARC, it gives me tons of errors.
EDIT: I changed code a little bit and go to a second part of a tutorial. Save/Load work correctly first run, but on second run it load correctly only once and when I trying to change score values I have exc_bad_access.
+(instancetype)loadInstance
{
pathString = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:#"gamedata"];
NSData* decodedData = [NSData dataWithContentsOfFile: pathString];
if (decodedData) {
//1
NSString* checksumOfSavedFile = [KeychainWrapper computeSHA256DigestForData: decodedData];
//2
NSString* checksumInKeychain = [KeychainWrapper keychainStringFromMatchingIdentifier: SSGameDataChecksumKey];
//3
if ([checksumOfSavedFile isEqualToString: checksumInKeychain]) {
RWGameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return gameData;
}
//4
}
return [[RWGameData alloc] init];
}
-(void)save
{
pathString = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:#"gamedata"];
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:pathString atomically:YES];
NSString* checksum = [KeychainWrapper computeSHA256DigestForData: encodedData];
if ([KeychainWrapper keychainStringFromMatchingIdentifier: SSGameDataChecksumKey]) {
[KeychainWrapper updateKeychainValue:checksum forIdentifier:SSGameDataChecksumKey];
} else {
[KeychainWrapper createKeychainValue:checksum forIdentifier:SSGameDataChecksumKey];
}
if([NSUbiquitousKeyValueStore defaultStore]) {
[self updateiCloud];
}
}
EXC_BAD_ACCSES on this line in my gamelayer after updated score:
[RWGameData sharedGameData].score += 1;
But if I call this line from init method - its working.
Check your +[RWGameData filePath] method implementation. It appears to be actually returning an array, not a string as expected.
You can see this from the "unrecognized selector" message, thrown by NSCFArray (which is an internal implementation of an NSArray). That array is complaining that someone is trying to access a method on it that only exists on strings. Since you're not doing that yourself directly, the -writeToFile:... method must be doing that on the result of -filePath on RWGameData.
I am showing image from URL in CCSprite. There are many images and hence i need to load image very quickly.
I have written my code which worked fine in simulator but crashed on iPad. Now i can't understand anything from the device log.
My code:
NSData *d = [NSData dataWithContentsOfURL:[NSURL URLWithString:[Data valueForKey:[NSString stringWithFormat:#"%d", idx]]]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%# %#", documentsDirectory, string];
BOOL didWrite = [d writeToFile:filePath atomically:YES];
CCSprite * facebookImage = [[CCSprite alloc] initWithFile:filePath] ;
Here I am saving my image in file and giving those content to CCSprite.
now the image from URL is fetching properly in simulator but on device this code crashes.
P.S : there are other ways too but they didn't work that well so i preferred this method over NSRequest etc.
Set a breakpoint, single-step through the code. Write probably fails because your path contains a space before the filename (format string: "%# %#"), or because string is nil.
Write failsafe code: you already have a didWrite flag, you should have an if clause that creates the sprite when write (and download) succeeded, otherwise log the error and perhaps create a placeholder sprite.
To display image from URL in CCSprite I have now changed my approach.
UIImage *uiimage2 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
CCSprite * facebookImage = [[CCSprite alloc]initWithCGImage:uiimage2.CGImage key:string];
Hope this answer helps someone.