Capturing Signature to Core Data - ios

I have an app that creates a field for the user to sign their name. Upon clicking the save signature I want to create the image, save it as a png, and save it to core data.
"Pilot Signature" is it's own entity, with the property image.
- (IBAction)saveSignature:(id)sender) {
NSData *imageData = UIImagePNGRepresentation(mySignatureImage.image);
// Create an image object for the new image.
NSManagedObject *image =
[NSEntityDescription insertNewObjectForEntityForName:#"Image"
inManagedObjectContext:self.managedObjectContext];
self.mySignatureImage = imageData;
// Set the image for the image managed object.
[image setValue:image forKey:#"PilotSignatureImage"];
}
I get one error and one warning when I invoke saveSignature
expected methody body
And on self.MySignature.image line I get
incompatible types assigning to 'UIImageView" from "NSManagedObject"
I've looked similar posts on here about how to save image to core data, and I'm not having any luck figuring out what I did differently.
Any help would be appreciated

This code has serious problems. First, this line is not valid Objective-C:
- (IBAction)saveSignature:(id)sender) {
That last ) should not be there. This would probably explain an "expected method body" error, because you're confusing the compiler.
There's no self.MySignature.image line. I'm guessing that you mean the line that assigns a value to self.mySignatureImage.
self.mySignatureImage = imageData;
What that error is telling you is that self.mySignatureImage is a UIImageView but that imageData is an NSManagedObject. You can't assign one of those to the other, because they're completely unrelated things. Maybe you meant to type self.mySignature.image here instead, since you mentioned that in your question?
Finally this line doesn't make any sense:
[image setValue:image forKey:#"PilotSignatureImage"];
You're assigning image as an attribute of itself. That's got to be wrong. Maybe you want to be assigning imageData here?
I'm guessing that the last couple of lines should look like this, but it's impossible to be certain from the question:
self.mySignature.image = imageData;
[image setValue:imageData forKey:#"PilotSignatureImage"];
From this question and other related questions that you've asked, I think you would do well to review some of the basics of Objective-C. You seem to be having basic problems that aren't directly related to Core Data or image handling.

Related

NSData Assignment Vanishes (becomes nil) Directly After Assigned

Let me start by saying I'm not proficient in objective c, nor am I an iOS developer. I'm working on a react-native app and find that I'm having to dig into the native code. So, I appreciate your patience with me and would also very much appreciate if you made zero assumptions about what I might, or might not know. Thx!
I'm trying to use react-native-mail but it fails to attach the photo I've selected to the email.
In troubleshooting, I jumped into Xcode's debugger for the first time. Stepping through the code, it appears as though the attachmentPath which is something like file:///var/mobile/... is being assigned to the variable fileData as type NSData. But then, taking one step further into the code it becomes nil.
I'm not sure why this would happen nor how to go about troubleshooting this. Here's an image of the debugger session with 3 screenshots stitched together side-by-side.
Here's the code: RNMail.m
All pointers, tips, guidance, and advice welcome
In your first screenshot, the debugger is still on the line that declares and assigns the fileData variable. This means that that line hasn't actually been executed yet. -dataWithContentsOfFile: hasn't yet been called, and thus the value that appears to be in fileData is not meaningful; what you're seeing is just garbage data prior to the variable actually being assigned. In your second screenshot, the -dataWithContentsOfFile: method has finished running, and it has returned nil. What you need to do is to figure out why you're getting nil from -dataWithContentsOfFile:. Perhaps the path to the file is incorrect, or perhaps you don't have permission to read it, or perhaps you have a sandboxing issue.
I would suggest using -dataWithContentsOfURL:options:error: instead of -dataWithContentsOfFile:. This will return an error by reference (create an NSError variable ahead of time, assign it to nil, pass a pointer to the error as the third parameter to -dataWithContentsOfURL:options:error:, and then check the error if the method returns nil). More likely than not, the contents of the error will explain what went wrong when trying to read the file.
EDIT: Looking at your screenshot again, the problem is clear; from the description of the contents of attachmentPath, we can see that it isn't a path at all, but instead it contains a URL string (with scheme file:). So you cannot pass it to the APIs that use paths. This is okay, since the URL-based mechanisms are what Apple recommends using anyway. So, just turn it into a URL by passing the string to -[NSURL URLWithString:] (or, even better, -[[NSURLComponents componentsWithString:] URL], since it conforms to a newer RFC). So, something like:
// Get the URL string, which is *not* a path
NSString *attachmentURLString = [RCTConvert NSString:options[#"attachment"][#"path"]];
// Create a URL from the string
NSURL *attachmentURL = [[NSURLComponents componentsWithString:attachmentURLString] URL];
...
// Initialize a nil NSError
NSError *error = nil;
// Pass a pointer to the error
NSData *fileData = [NSData dataWithContentsOfURL:attachmentURL options:0 error:&error];
if (fileData == nil) {
// 'error' should now contain a non-nil value.
// Use this information to handle the error somehow
}

Is there a way to refresh the cache used by UIImage class?

In my iOS app I am using the +imageNamed: method to load an image (many times and in many different places in the code).
In one case the user might update (download) a new image.
When I try to load the new, it will show the old, due to caching.
From the "Is there a way to clear the cache used by UIImage class?" question, I saw that I have to use the -initWithContentsOfFile: method.
But this will not take advantage of the caching speedup that the +imageNamed: enjoys. All I want is to "tell" the cache that the file has changed, so it needs to "re-cache" it. And then keep using the +imageNamed: method with the new cached image.
In other words, I use the +imageNamed: method (say) 10 times, I change the image, I "tell" the cache, then I continue use the +imageNamed: method another (say) 10 times. If I change all the +imageNamed: to -initWithContentsOfFile: then I lose the caching advantage.
Is there a way/trick to do that?
There is no API for clearing the cache. If your app is not destined for the app store you could call the private method:
[UIImage _flushSharedImageCache];
However I wouldn't want this anywhere near production code.
Instead I would create a category on UIImage and add a method for returning the desired image from a filename. This name would be stored and then updated when your new image is downloaded. You will get the benefit of caching, without any hacky workarounds.
Depending on the complexity of your project, a simple find and replace shouldn't take too long.
Although I'm now questioning how your app is working currently, imageNamed only looks for files in your app's bundle, so won't work for images downloaded by the user.
You'll probably just have to figure out your own way of caching your images.
I'd suggest using a UIImage category with a static NSMutableDictionary that can hold your cached images. Then just use your custom caching method when initialising your UIImage.
For example:
#interface UIImage (UIImageCache)
+(UIImage*) cachedImageFile:(NSString*)imageFile;
+(void) resetCacheForImageFile:(NSString*)imageFile;
#end
#implementation UIImage (UIImageCache)
static NSMutableDictionary* cachedImages;
+(UIImage*) cachedImageFile:(NSString*)imageFile {
// Optional error checking
NSAssert1([[NSFileManager defaultManager] fileExistsAtPath:imageFile], #"Warning! The image file %# doesn't exist.", imageFile);
if (!cachedImages) cachedImages = [NSMutableDictionary dictionary];
UIImage* cachedImg = [cachedImages objectForKey:imageFile];
if (cachedImg) return cachedImg; // Image is cached, return it
else { // No cached image, create one
UIImage* img = [UIImage imageWithContentsOfFile:imageFile]; // iOS won't auto-cache the image.
[cachedImages setObject:img forKey:imageFile];
return img;
}
}
+(void) resetCacheForImageFile:(NSString*)imageFile {
[cachedImages removeObjectForKey:imageFile];
}
#end
Maybe I just got late to the party...but using
+ (UIImage *)imageWithContentsOfFile:(NSString *
I got rid of the cache issue.
Hope it helps!!

Set attribute to managed object

I'm fairly new to ios development and I'm trying to set some imagedata as an attribute of a mangedobject I've created.
I've read, and re-read the apple docs and can't seem to find what I'm looking for. I know it must be something simple I'm missing but I can't put my finger on it.
If anyone could point me in the right direction i would really appreciate it!
here's my current code:
-IBAction saveSignature: (id) Sender {
NSData *imageData = UIImagePNGRepresentation(mySignature.image);
NSManagedObject *pilotSignature = [[NSEntityDescription
insertnewObjectForEntityForName:#"pilotsignature"
inManagedObjectContext: selfmanagedObjectContext]]

UIImages NSURLs and Threads

I am trying to build a nice function to access the network for images, if they are found on the web, I store them in a cache system I made.
If the image was already stored on the cache, I return it.
The function is called getImageFromCache and returns an image if it is in the cache, else, it would go to the network and fetch.
The code might look like this:
UIImageView* backgroundTiles = [[UIImageView alloc] initWithImage[self getImageFromCache:#"http://www.example.com/1.jpg"]];
Now, I am moving on to using threads because of big latencies due to network traffic. So I want images to show a temp image before I get the result from the web.
What I want to know is how can I keep track of so many images being accessed sequentially, being added to UIImageViews by this function (getImageFromCache).
Something just won't work there:
-(UIImage*)getImageFromCache:(NSString*)forURL{
__block NSError* error = nil;
__block NSData *imageData;
__block UIImage* tmpImage;
if(forURL==nil) return nil;
if(![self.imagesCache objectForKey:forURL])
{
// Setting a temporary image until we start getting results
tmpImage = [UIImage imageNamed:#"noimage.png"];
NSURL *imageURL = [NSURL URLWithString:forURL];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
imageData = [NSData dataWithContentsOfURL:imageURL options:NSDataReadingUncached error:&error];
if(imageData)
{
NSLog(#"Thread fetching image URL:%#",imageURL);
dispatch_async(dispatch_get_main_queue(), ^{
tmpImage = [UIImage imageWithData:imageData];
if(tmpImage)
{
[imagesCache setObject:tmpImage forKey:forURL];
}
else
// Couldn't build an image of this data, probably bad URL
[imagesCache setObject:[UIImage imageNamed:#"imageNotFound.png"] forKey:forURL];
});
}
else
// Couldn't build an image of this data, probably bad URL
[imagesCache setObject:[UIImage imageNamed:#"imageNotFound.png"] forKey:forURL];
});
}
else
return [imagesCache objectForKey:forURL];
return tmpImage;
}
This is not a direct answer to your question, but are you aware that there is no need to use GCD to download things asynchronously (on a background thread)? Just use NSURLConnection and its delegate methods. All your code will be on the main thread but the actual connection and downloading will happen in the background.
(And in fact I have written a class, MyDownloader, that takes care of all this for you:
http://www.apeth.com/iOSBook/ch37.html#_http_requests
Scroll down to the part about MyDownloader and its subclass MyImageDownloader, which is doing exactly the sort of thing you need done here. Moreover, note the subsequent code in that chapter showing how to use a notification when a download completes, prompting the table view that need these images to reload the row that contains the image view whose image has just arrived.)
its good your building it from scratch but if you want to save the all the work, there's a drop in Replacement SDWebImage Library with support for remote images coming from the web, and has all the functionality Like Temp Image, Asychronous Loading, Caching etc, you said you need
In your background thread, once the download has completed and you've saved the image to the cache, I'd suggest you post a notification using the NSNotificationCenter to let other parts of your app know that the cache has been updated.
This assumes that whichever part of the app manages the image views has registered its interest in those notification with the addObserverForName method. When it receives such a notification, it can then attempt to retrieve the images from the cache again and update its image views if appropriate.
Depending on the number of image views, you may want to pass through the image url in the notification in some way (e.g. in the userInfo dictionary), and then based on that decide which image views should be refreshed rather than refreshing them all.
I should add that I would also recommend getting rid of the inner dispatch_async call. There's no need for that, although you may need to add synchronisation to your cache object so it can be safely accessed from the main thread as well as the download thread.

stringWithContentsOfFile and initWithContentsOfFile return null after several runs

I am creating an iOS app which reads in a text file and displays the contents in a UIText field.
For the 1st three consecutive runs of thee app (Restarting a new session without exiting),
the data is read in fine. However on the fourth attempt, the data returned from the file is all nulls.
I've verified the file integrity. The issue exists when using stringWithContentsOfFile or initWithContentsOfFile.
After many hours of troubleshooting, I believe the issue is somehow related to a buffer being cleared within the above mentioned methods.
Any insight regarding this issue is greatly appreciated. I've tried many things with no luck.
Here's the code I use to read in the file:
TheString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"My_TextFile" ofType:#"txt"] encoding:NSUTF8StringEncoding error:NULL];
Here's the code I use to display certain contents of the file (The contents are placed in an array of type NSArray):
NSArray *My_Array;
My_Array= [TheString componentsSeparatedByString:#"\n"];
/* Obtain specific data to display */
DisplayedData = [My_Array objectAtIndex:M[l]-1];
:
:
/* Display the data in the view */
MyUITextView.text = DisplayedData;
/* Log the data */
NSLog(#"%#", MyUITextView.text);
On the 4th invocation of the code above, the data returned is blank and NSLOG is returning nulls
Thanks so much for any help!
Maybe I'm a little bit late with answer, but, anyway, maybe somebody will find it useful.
OK, I have also spent a day trying to figure out why my custom class for scrollable view is working 3 times and refuse at the 4-th time... I found that the problem has quite the same attributes as yours: nested NSString objects unexpectedly disappear. Though pointers point to the same address in memory, memory is already filled with quite arbitrary objects instead my NSStrings.
And I paid attention that I created these NSStrings using the following class method:
+ (id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
So, I'm not the owner of these NSStrings.
And I assumed that to be the owner can be a solution, so I created my NSStrings through alloc and
- (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
instance method.
App was repaired!

Resources