Need to see which UIImageView is empty and place an image there - ios

Here's my problem. I have 3 UIImageViews that are empty by default, placed on a UIView that are is hidden at first.
And they are supposed to be filled one after another when a user selects something.
I know it sounds confusing, but I think my code below will clear things out:
- (IBAction)selectButtonPressed:(id)sender {
if ([labelText.text isEqualToString:#"some text"]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"someImage"] ofType:#"png"];
UIImage * image = (UIImage * )[UIImage imageWithContentsOfFile:filePath];
if (firstImage.image == nil) {
firstImage.image = image;
imagesView.hidden = YES;
firstImage.hidden = NO;
} // places it in the first Image View if it's empty ...
else if (secondImage.image == nil) {
secondImage.image = image;
imagesView.hidden = YES;
secondImage.hidden = NO;
} // ... or in the second one if empty
else {
thirdImage.image = image;
imagesView.hidden = YES;
thirdImage.hidden = NO; // ... else in the third one
}
[filePath release];
[image release];
}
// then does the same thing depending on the users selection.
else if ([labelText.text isEqualToString:#"some other text"]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"someOtherImage"] ofType:#"png"];
UIImage * image = (UIImage * )[UIImage imageWithContentsOfFile:filePath];
if (firstImage.image == nil) {
firstImage.image = image;
imagesView.hidden = YES;
firstImage.hidden = NO;
}
else if (secondImage.image == nil) {
secondImage.image = image;
imagesView.hidden = YES;
secondImage.hidden = NO;
}
else {
thirdImage.image = image;
imagesView.hidden = YES;
thirdImage.hidden = NO;
}
[filePath release];
[image release];
}
// and same thing below if none of the above.
else {
NSString *filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"yet another text"] ofType:#"png"];
UIImage * image = (UIImage * )[UIImage imageWithContentsOfFile:filePath];
if (firstImage.image == nil) {
firstImage.image = image;
imagesView.hidden = YES;
firstImage.hidden = NO;
}
else if (secondImage.image == nil) {
secondImage.image = image;
imagesView.hidden = YES;
secondImage.hidden = NO;
}
else {
thirdImage.image = image;
imagesView.hidden = YES;
thirdImage.hidden = NO;
}
[filePath release];
[image release];
} // Code for checking which Image View is empty and place the image there.
}
So, it launches and works fine, when I do the first selection. But for the 2nd one it says EXC_BAD_ACCESS and crashes. Sometimes it works for the first 2 selections and for the third one it crashes.
Please let me know if it's confusing, I'll try to explain my intent as clear as I can.
Thanks a lot
UPDATE: Well, I think it's true that an answer appears when you ask the right question.
Everything worked well, after I've used firstImage.image = [UIImage imageNamed:#"someImage"]; instead of the whole NSBundle method. Code became cleaner and works like a charm.
However I'm not sure if there are any downsides to this. So if you guys can warn me of anything, I'm all opened to that.
Thanks again.

Your problem probably related to your memory management. Did you use property for those imageview? Also, you don't need to release filePath and image because you did not use the alloc, etc. method to initialize it.

Related

Can't Revert Back to Original Image After Using UIImagePickerController

I am having an interesting little problem using the uiimagepickercontroller and was wondering if anyone has any insight as to what might be happening. Users can take pictures with the camera or pick from the photo library until the cows come home as many times in a row as they like. My issue lies in allowing users to revert back to the original image that shipped with the app. Here is the flow:
Users go the the tableview which shows a thumbnail of the image.
Users navigate to the detail view which shows a larger view of the image.
Users can tap on the image in the detail view to bring up a custom alertcontroller with options to a) use the camera to take a picture, b) use a picture from their library, or c) revert back to the original image.
Users choose either option 'a' or option 'b' to either take a picture or use a picture from the photo library. IF they IMMEDIATELY change their mind about using one of those choices and want to just go back to using the original image, nothing happens! They can snap another picture or choose another image right away, but cannot revert back to the original image right away.
Reverting back to the original image DOES work perfectly when the app has been closed and then opened again. Sometimes it will work if you navigate around to other views within the app and then come back to the detail view where they just added their own image. By why the delay? I've searched around for two weeks but have not found anything resembling my problem or any solutions that help in any way (like reloading the headerview where image is sitting). Any thoughts?
Also I have figured out how to save the image to iCloud by using the documentation but cannot figure out how to retrieve them so there is no code for that. That is entirely different question. The same thing seems to occur even without that code.
Thanks for taking the time to look at this!
Here is some code:
-(void)bookImageTapped:(UIGestureRecognizer *)gesture
{
URBAlertView *changeImageAlertView = [[URBAlertView alloc] initWithTitle:#"Add A New Book Cover Image" message:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Use Camera", #"Open Gallery", #"Use Original Photo", nil];
[changeImageAlertView setHandlerBlock:^(NSInteger buttonIndex, URBAlertView *alertView) {
[self checkPermission];
if (PHAuthorizationStatusAuthorized)
{
if(buttonIndex == 0)
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerController.delegate = self;
pickerController.allowsEditing = NO;
pickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:pickerController animated:YES completion:nil];
}];
[alertView hide];
}
else
{
NSLog(#"Camera not available");
[alertView hide];
}
}
else if (buttonIndex == 1)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
pickerController.delegate = self;
pickerController.allowsEditing = NO;
pickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:pickerController animated:YES completion:nil];
}];
[alertView hide];
}
else if (buttonIndex == 2)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self restoreOriginalPhoto];
}];
[alertView hide];
}
else
{
NSLog(#"button 2 cancel");
[alertView hide];
}
}
}];
[changeImageAlertView show];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info
{
[picker dismissViewControllerAnimated:YES completion:nil];
_book.largeBookImage = [info objectForKey:UIImagePickerControllerOriginalImage];
_book.largeBookImage = [self scaleImage:_book.largeBookImage toSize:CGSizeMake(120, 168)];
_bookImageView.image = _book.largeBookImage;
_book.wasNewImageAdded = YES;
_book.originalImageUsed = NO;
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:_book.largeBookImage withFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
-(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath
{
if ([[extension lowercaseString] isEqualToString:#"png"])
{
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"png"]] options:NSAtomicWrite error:nil];
//Create a URL to the local file
NSURL *resourceURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"png"]]];
if (resourceURL)
{
CKAsset *asset = [[CKAsset alloc] initWithFileURL:resourceURL];
//create a record object
CKRecord *bookCover = [[CKRecord alloc] initWithRecordType:#"Bookcover"];
//set the record's fields
bookCover[#"title"] = _book.title;
bookCover[#"bookImage"] = asset;
/* TO SAVE A RECORD */
//get the public database
CKContainer *appContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [appContainer publicCloudDatabase];
[publicDatabase saveRecord:bookCover completionHandler:^(CKRecord *bookCover, NSError *error) {
if (error)
{
//insert error handling
return;
}
//insert succesfully saved record code
NSLog(#"png record saved after using picker!");
}];
}
}
else if ([[extension lowercaseString] isEqualToString:#"jpg"] || [[extension lowercaseString] isEqualToString:#"jpeg"])
{
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"jpg"]] options:NSAtomicWrite error:nil];
//Create a URL to the local file
NSURL *resourceURL = [NSURL fileURLWithPath:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"jpg"]]];
if (resourceURL)
{
CKAsset *asset = [[CKAsset alloc] initWithFileURL:resourceURL];
//create a record object
CKRecord *bookCover = [[CKRecord alloc] initWithRecordType:#"Bookcover"];
//set the record's fields
bookCover[#"title"] = _book.title;
bookCover[#"bookImage"] = asset;
/* TO SAVE A RECORD */
//get the public database
CKContainer *appContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [appContainer publicCloudDatabase];
[publicDatabase saveRecord:bookCover completionHandler:^(CKRecord *bookCover, NSError *error) {
if (error)
{
//insert error handling
return;
}
//insert succesfully saved record code
NSLog(#"jpg record saved after using picker!");
}];
}
}
else
{
NSLog(#"Image Save Failed\nExtension: (%#) is not recognized, use (PNG/JPG)", extension);
}
}
- (UIImage *) scaleImage:(UIImage*)image toSize:(CGSize)newSize
{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
-(void)restoreOriginalPhoto
{
NSLog(#"restore photo called");
_book.originalImageUsed = YES;
_book.wasNewImageAdded = NO;
_bookImageView.image = _book.largeBookImage;
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:_book.largeBookImage withFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
}
Here is the headerview with the imageview:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
_headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 26)];
_headerView.backgroundColor = [UIColor colorWithRed:8/255.0 green:46/255.0 blue:46/255.0 alpha:0.8];
if (section == 0)
{
_headerView.backgroundColor = [UIColor whiteColor];
_bookImageView = [[UIImageView alloc] initWithFrame:CGRectMake((tableView.frame.size.width - 120)/2, 6, 120, 168)];
_bookImageView.contentMode = UIViewContentModeScaleAspectFit;
if (_book.wasNewImageAdded)
{
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
_bookImageView.image = image;
}
else
{
_bookImageView.image = _book.largeBookImage;
}
if(_book.originalImageUsed)
{
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
_bookImageView.image = image;
}
UITapGestureRecognizer *bookImageTouched = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(bookImageTapped:)];
bookImageTouched.numberOfTapsRequired = 1;
[_bookImageView addGestureRecognizer:bookImageTouched];
_bookImageView.userInteractionEnabled = YES;
[_headerView addSubview:_bookImageView];
}
I finally figured it out! It seems that I was confusing xcode with my property names. The code ended up much simpler in the end.
In didFinishPickingMediaWithInfo I created a UIImage and then set it to the bookImageView.image. Later, when I wanted to be able to update the image back to the original image, then I could call the bundle asset, _book.largeBookImage. Voila! The image was able to update immediately.
The most pertinent code is posted below.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info
{
[picker dismissViewControllerAnimated:YES completion:nil];
_chosenImage = [[UIImage alloc] init];
_chosenImage = [info objectForKey:UIImagePickerControllerOriginalImage];
_bookImageView.image = _chosenImage;
_book.wasNewImageAdded = YES;
_book.originalImageUsed = NO;
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:_chosenImage withFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
}
-(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath
{
if ([[extension lowercaseString] isEqualToString:#"png"])
{
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"png"]] options:NSAtomicWrite error:nil];
[self.tableView reloadData];
}
else if ([[extension lowercaseString] isEqualToString:#"jpg"] || [[extension lowercaseString] isEqualToString:#"jpeg"])
{
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"jpg"]] options:NSAtomicWrite error:nil];
[self.tableView reloadData];
}
else
{
//NSLog(#"Image Save Failed\nExtension: (%#) is not recognized, use (PNG/JPG)", extension);
}
}
-(void)restoreOriginalPhoto
{
_book.originalImageUsed = YES;
_book.wasNewImageAdded = NO;
_bookImageView.image = _book.largeBookImage;
_backgroundImage.image = _book.largeBookImage;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0)
{
_bookImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120, 168)];
_bookImageView.contentMode = UIViewContentModeScaleAspectFit;
_bookImageView.clipsToBounds = YES;
_bookImageView.layer.cornerRadius = 10.0f;
if (_book.wasNewImageAdded)
{
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:_book.bookImageID ofType:#"jpg" inDirectory:documentsDirectory];
_bookImageView.image = image;
}
else
{
_bookImageView.image = _book.largeBookImage;
}
if(_book.originalImageUsed)
{
_bookImageView.image = _book.largeBookImage;
}
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(_book.originalImageUsed)
{
_bookImageView.image = _book.largeBookImage;
}
[self.tableView reloadData];
[self.tableView setContentOffset:CGPointZero animated:NO];
}

Flipping a UIImage horizontally in UIImageView

In my project, I have my image files stored in jpeg format. The code below "works" in that it doesn't crash, but my images don't flip when they're supposed to. I threw a breakpoint in to ensure that the code is running--it is, but the images that are displayed aren't flipped. I'm guessing I'm missing something basic, but it's not jumping out at me.
if (self.isTimer == YES) {
// this is where images get dumped if they exist
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.currentItem.photo != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d", self.currentItem.photo, imageNumber];
if ([UIImage imageNamed:fileName]) {
UIImage *image = [UIImage imageNamed:fileName];
// test whether count is even or odd
if (self.currentItem.sideMultiplier.intValue == 1) {
// if there's only one side to be done, dump unflipped images in array
[imageArray addObject:image];
NSLog(#"regular image added to array");
} else {
// if there are 2 sides, determine if it's even or odd side
if (self.stretchSideMultiplierCount % 2 == 1) {
// add a unflipped image to the array
[imageArray addObject:image];
NSLog(#"regular image added to array");
} else {
// ** I want to add a FLIPPED IMAGE here
UIImage *flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUpMirrored];
[imageArray addObject:flippedImage];
NSLog(#"flipped image added to array");
}
}
NSLog(#"%# added to imageArray", fileName);
} else {
break;
}
}
I followed this post, but nothing's happening.
How to flip UIImage horizontally?
I added #import <QuartzCore/QuartzCore.h> to my implementation file. Aside from that, I'm out of ideas re: how to flip an image horizontally.
UPDATE: Much easier solution
Rather than flipping the UIImage, I flipped the UIImageView. The code above I used to create my imageArray now looks like this:
if (self.isTimer == YES) {
// this is where images get dumped if they exist
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.currentItem.photo != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d", self.currentItem.photo, imageNumber];
if ([UIImage imageNamed:fileName]) {
UIImage *image = [UIImage imageNamed:fileName];
[imageArray addObject:image];
NSLog(#"image added to array");
NSLog(#"%# added to imageArray", fileName);
} else {
break;
}
}
and the code I used to flip my UIImageView is in the answer below.
Problem solved. Rather than flipping the UIImage, I flipped the UIImageView as follows:
self.myImageView.transform = CGAffineTransformMakeScale(-1, 1);

Issue using displaying Image with NSMutableArray

I am very new to xcode and I am playing around with image arrays and NSMutableArray. When I run the code below it just print out the names of the image for example "image1.png". Any tips to fix this problem would be appreciated. Thanks.
- (NSMutableArray*)restaurantArray;
{
if (_restaurantArray == nil) {
_restaurantArray = [[NSMutableArray alloc] initWithObjects:
#"image1.png",
#"image2.png",
#"image3.png",
nil];
}
return _restaurantArray;
}
-(NSString*) randomRestaurant
{
int random = arc4random_uniform(self.restaurantArray.count);
return [self.restaurantArray objectAtIndex:random];
}
You could do it in this way also.
- (NSMutableArray*)restaurantArray;
{
if (_restaurantArray == nil) {
_restaurantArray = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
[UIImage imageNamed:#"image3.png"],
nil];
}
return _restaurantArray;
}
Do you mean this?:
NSString *imageName = [self randomRestaurant];
UIImage *image = [UIImage imageName:imageName];
If you want to display the image then do this:
Suppose you have an imageview name imgView,
imgView.image = [UIImage imageNamed:[self randomRestaurant]];
Or, if you just want the image, then call this:
UIImage *img = [UIImage imageNamed:[self randomRestaurant]];
In you given code, you are just returning the name of the image, not the actual image. If you want an array of image then you can do it by this way:
-(NSMutableArray*) restaurantArray;
{
if (_restaurantArray == nil) {
UIImage *img = [UIImage imageNamed:#"image1.png"];
UIImage *img1 = [UIImage imageNamed:#"image2.png"];
UIImage *img2 = [UIImage imageNamed:#"image3.png"];
_restaurantArray = [[NSMutableArray alloc] initWithObjects:
img,
img1,
img2,
nil];
}
return _restaurantArray;
}
-(UIImage*) randomRestaurant
{
int random = arc4random_uniform(self.restaurantArray.count);
return [self.restaurantArray objectAtIndex:random];
}
Hope this helps.. :)

Load many gif to UICollectionView

I am facing problem when I download gif images and add in to collection view.
gif images are download well, but when i try to scroll very very quickly it's crash
Please help. I have two solutions
/*
cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
cellForGif.layer.borderWidth = 0.7;
FLAnimatedImage __block *gifImage = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%li", (long)indexPath.row] ofType:#"gif"]]];
dispatch_async(dispatch_get_main_queue(), ^{
cellForGif.gifImage.animatedImage = gifImage;
cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
//gifImage = nil;
});
});
return cellForGif;
*/
cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
cellForGif.layer.borderWidth = 0.7;
FLAnimatedImage *gifImage = nil;
gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%li", (long)indexPath.row] ofType:#"gif"]]];
cellForGif.gifImage.animatedImage = gifImage;
cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
//gifImage = nil;
return cellForGif;
You need to change your approach.
You have to load all images before going to set them in UICollectionViewCell.
Let's say create an NSArray contains all gif images. After images are loaded successfully then set them to the cell.
By observing straight from your code, I see that you load an image from the main bundle in cellForItemAtIndexPath method. So it is obvious that it will take some time very little (nano sec). But that is also considered large when there are a large amount of data in a cell.
And it is possible that line
[NSData dataWithContentsOfFile:[[NSBundle mainBundle]
will return nil when you scroll very very quickly.
Add a comment if it is still not clear.
EDIT:
Loading images in the background will not affect UI and scrolling will be smoother.
Also, put try-catch block in that method to check what you have missed.
cellForGif.layer.borderColor = [[UIColor colorWithRed:54.0/255.f green:56.0/255.f blue:67.0/255.f alpha:1.0]CGColor];
cellForGif.layer.borderWidth = 0.7;
#try {
FLAnimatedImage __block *gifImage = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
gifImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%li", (long)indexPath.row] ofType:#"gif"]]];
dispatch_async(dispatch_get_main_queue(), ^{
cellForGif.gifImage.animatedImage = gifImage;
cellForGif.linkOnGif = [self.linksArrayOnGifs objectAtIndex:indexPath.row];
//gifImage = nil;
});
});
}
#catch (NSException *exception) {
NSLog(#"Exception :%#",exception.debugDescription);
}
swift extension based on Kampai's answer:
extension UIImageView {
func setGif(_ url: String) {
DispatchQueue.global(qos: .default).async {
do {
let gifData = try Data(contentsOf: URL(string: url) ?? URL(fileURLWithPath: ""))
DispatchQueue.main.async {
self.image = UIImage.sd_image(withGIFData: gifData)
}
} catch let error {
DispatchQueue.main.async {
self.image = UIImage(named: "defaultImg")// set default image here
}
print(error)
}
}
}
}
use it as:
cell.imageGif.setGif("image url")

Rendering the layer of a UIWebView that contains an SVG file

I am attempting to use this method I've constructed to save the layer of a UIWebView as an image. That is working but the SVG I have loaded into the UIView is not getting rendered in the image, only the background of the UIWebView.
+ (BOOL)imageFromSVGinWebView:(UIView *)theView usePNG:(BOOL)usePNG; {
UIGraphicsBeginImageContext(theView.frame.size);
[theView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *layerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *layerIMGData = nil;
NSString *pathComponent = nil;
if (usePNG) {
layerIMGData = UIImagePNGRepresentation(layerImage);
pathComponent = #"png";
}else {
layerIMGData = UIImageJPEGRepresentation(layerImage,1.0f);
pathComponent = #"jpg";
}
NSString *appFile = [[CCFileManagement conversionsDirectory] stringByAppendingPathComponent:String(#"img.%#",pathComponent)];
NSError *error = nil;
BOOL returnBOOL = [layerIMGData writeToFile:appFile options:NSDataWritingAtomic error:&error];
if(error != nil)
ILogPlus(#"%#",error);
return returnBOOL;
}
In summary, I've loaded an SVG into a UIWebView, saved that UIWebView as an image, opened the image and the image does not have the SVG in it. I have done this with other views successfully, something is different about the SVG or UIWebView.
UPDATE:
If I add a delay to make the app wait a few seconds to execute the image saving code then it works. Putting that code in webViewDidFinishLoad does NOT work. Obviously webViewDidFinishLoad doesn't count SVGs.
I have found that if you add a .1 second delay it will work
- (void)webViewDidFinishLoad:(UIWebView *)webView; {
[self performSelector:#selector(postLoadActions:) withObject:webView afterDelay:0.1f];
}
- (void)postLoadActions:(UIWebView *)webView; {
if (![CCConversion imageFromSVGinWebView:webView usePNG:YES]) {
ILogPlus(#"Didn't work");
}
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[CCFileManagement conversionsDirectory] error:NULL];
ILogPlus(#"%#",array);
//[webView removeFromSuperview];
[webView release];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[CCFileManagement conversionsDirectory] stringByAppendingPathComponent:#"img.png"]]];
imageView.frame = CGRectMake(90, 90, imageView.frame.size.width, imageView.frame.size.height);
imageView.backgroundColor = [UIColor clearColor];
[self.view performSelector:#selector(addSubview:) withObject:imageView afterDelay:2.0f];
[imageView release];
}

Resources