I've written some code to make a screenshot of the view. I write that image to the photo library. But the thing is, I want to use that image in an other imageView in another ViewController. How can I save the image somewhere in the app and use it in another ViewController?
My code:
UIView* captureView = self.view;
UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, captureView.opaque, 0.0);
[captureView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect cropRect = CGRectMake(0 ,0 ,640,1136);
UIGraphicsBeginImageContextWithOptions(cropRect.size, captureView.opaque, 1.0f);
[screenshot drawInRect:cropRect];
UIImage * customScreenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(customScreenShot , nil, nil, nil);
You first need to save your image on the disk:
NSString *documentDirectory =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
objectAtIndex:0];
NSString *pngFilePath = [NSString stringWithFormat:#"%#/myImage.png",documentDirectory];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(customScreenShot)];
[imageData writeToFile:pngFilePath atomically:YES];
And then you can create an UIImageView with the file:
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage
imageWithContentsOfFile:pngFilePath]];
[self.view addSubview:myImageView];
If you are using Storyboards, you could pass it to the next view controller like so; in the prepareForSegue method ( this relieves you from having to save it to disk ):
Note: the name of the segue is set by you in MainStoryboard.storyboard. - mySegue.
kMySegue is just a key for that. i.e. #define kMySegue #"mySegue"
imageInOtherViewController is a UIImage in the other view controller.
// TheFirstViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
id destinationViewController = [segue destinationViewController];
if ([[segue identifier] isEqualToString:kMySegue]){
if ([destinationViewController respondsToSelector:#selector(setImageInOtherViewController:)]){
[destinationViewController setImageInOtherViewController:[UIImage imageNamed:#"myImage.png"]];
FastCameraViewController *viewController = segue.destinationViewController;
viewController.delegate = self;
}
}
// OtherViewController.h
#interface OtherViewController : UIViewController
{
}
#property (nonatomic, strong) IBOutlet UIImageView *otherViewControllerImageView;
#property (nonatomic, strong) UIImage *imageInOtherViewController;
// OtherViewController.m
#implementation OtherViewController
#synthesize otherViewControllerImageView;
#synthesize imageInOtherViewController;
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[self otherViewControllerImageView] setImage:imageInOtherViewController];
}
To cache your images I recommend using the NSCache class first ie
NSCache* imagesCache = [[NSCache alloc] init];
[imagesCache setName:#"imagesCache"];
[imagesCache setObject:customScreenShot forKey:#"image1"];
the good news is that NSCache accepts any object of type id so you can store images, mp3s, whatever you want.
If you would like to use the phone's file directory (which is more expensive to use than NSCache..) I recommend you use the Library/Caches directory instead of the Documents directory.. so building on iDevzilla's answer:
NSString *documentDirectory =
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
objectAtIndex:0];
Related
I have the following issue:
I have one instance from class that extends UIViewController class, in this class i am adding UIImage to UIImageView, and then adding the UIImageView to the self.view using this method "addSubview:" [self.view addSubview:imageView] and finally adding the self.view to the window using [[[UIApplication sharedApplication] keyWindow] addSubview:[self view]] , and when i click on a close button i am clearing the self.view (removing the subview "UIImageView") and removing the self.view from the window.
now the issue is when i am using the same instance to add other UIImageView with other image, the first data is not freed from the memory even i have released them and removed them from the superview. the following code illustrates the problem.
- (void) setImageWithURL: (NSString *)url {
NSData * imageData =NSData * imageData =[NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
if (imageData) {
UIImage *image = [[UIImage alloc]initWithData:imageData];
[[[UIApplication sharedApplication] keyWindow] addSubview:[self view]];
[self createViewWithImage:image];
[image release];
}
-(void) createViewWithImage: (UIImage *) image{
[self.view setHidden:false];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
[imageView release];
}
// for removing the imageView when i click on close button
-(void) closeView{
for (UIView *subView in self.view.subviews) {
[subView removeFromSuperview];
}
[self.view removeFromSuperview];
}
Note: I have used the xcode instruments to test the memory allocation.
UPDATE:
after more research .. it is not addSubview & removeFromSuperview that make memory leaks.. its NSData. I dont why its not released from the memory. I have made some changes to test if its truly the NSData, i saved the image locally and set the image using two cases:
//Case 1:
NSString *path = [[NSBundle mainBundle] pathForResource:#"image" ofType:#"png"];
NSData * imageData =[[NSData dataWithContentsOfFile:path];
image = [[UIImage alloc]initWithData:imageData];
//Case 2:
NSString *path = [[NSBundle mainBundle] pathForResource:#"image" ofType:#"png"];
image = [[UIImage alloc] initWithContentsOfFile:path];
I have found that case one makes memory leaks, while case 2 is clean.
now UIImage cant take the image without using the NSData, and for some reason NSData is not released .. so how can i fix this problem !!!!
Do you have a:
[super dealloc];
in your deriving class's dealloc?
In this code a user gets and displays a photo (provided for now) in ImageViewController, adds a caption, and the the photo and caption are passed to the MTViewcontroller where it is made into a pdf. I have solved the PDF portion, but struggling with the segue. Appreciate any guidance. I can't find an example quite like this.
ImageViewController.h
#import <UIKit/UIKit.h>
#interface ImageViewController : UIViewController
{
NSURL *url;
UIImage *imageRoll;
}
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#property (strong, nonatomic) IBOutlet UITextField *enterCaption;
- (IBAction)Button:(id)sender;
#end
ImageViewController.m Not sure I'm treating imageRoll correctly and I can't find the right segue format for this. Once the user, submits the caption it would segue to the PDF controller. BUT, would the keyboard release given the segue?
- (void)viewDidLoad
{
[super viewDidLoad];
// Since iPhone simulator doesn't have photos, load and display a placeholder image
NSString *fPath = [[NSBundle mainBundle] pathForResource:#"IMG_3997" ofType:#"jpg"];
url = [NSURL fileURLWithPath:fPath];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
UIImage *imageRoll = [UIImage imageWithContentsOfFile:fPath];
}
// User provides a caption for the image
- (IBAction)Button:(id)sender {
NSString *caption = enterCaption.text;
[self performSegueWithIdentifier:#"showPDF" sender:sender];
MTViewController *vc1 = [segue destinationViewController];
vc1.photoCaption = caption;
MTViewController *vc2 = [segue destinationViewController];
vc2.photoImage = imageRoll;
}
//Dismiss Keyboard
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
MTViewController.h
#import <UIKit/UIKit.h>
#import "ReaderViewController.h"
#interface MTViewController : UIViewController <ReaderViewControllerDelegate>
#property(nonatomic, assign) NSString *photoCaption;
#property(nonatomic, assign) UIImage *photoImage;
- (IBAction)didClickMakePDF:(id)sender;
#end
MTViewController.m Have I passed and used photoCaption and photoImage correctly?
- (IBAction)didClickMakePDF {
[self setupPDFDocumentNamed:#"NewPDF" Width:850 Height:1100];
[self beginPDFPage];
CGRect textRect = [self addText:photoCaption
withFrame:CGRectMake(kPadding, kPadding, 400, 200) fontSize:48.0f];
CGRect blueLineRect = [self addLineWithFrame:CGRectMake(kPadding, textRect.origin.y + textRect.size.height + kPadding, _pageSize.width - kPadding*2, 4)
withColor:[UIColor blueColor]];
UIImage *anImage = [UIImage imageNamed:#"photoImage"];
CGRect imageRect = [self addImage:anImage
atPoint:CGPointMake((_pageSize.width/2)-(anImage.size.width/2), blueLineRect.origin.y + blueLineRect.size.height + kPadding)];
[self addLineWithFrame:CGRectMake(kPadding, imageRect.origin.y + imageRect.size.height + kPadding, _pageSize.width - kPadding*2, 4)
withColor:[UIColor redColor]];
[self finishPDF];
}
updated:
You should use self.xxx = xxx to save it in one method and get it back in another method by using self.xxx. For example you should use
self.imageRoll = [UIImage imageWithContentsOfFile:fPath];
instead of declaring a new imageRoll in your code. And it's the same with your caption.
The way you use segue is incorrect.
The way you call [self performSegueWithIdentifier:#"showPDF" sender:sender]; is correct. But then you can do some customization in
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPDF"]) {
MTViewController *vc1 = [segue destinationViewController];
vc1.photoCaption = self.caption;
vc1.photoImage = self.imageRoll;
}
}
I'm trying to displaying an image from file on my ViewController in Xcode. I have in my ViewController.h:
UIImageView *image;
#property(nonatomic,retain) IBOutlet UIImage* image ;
ViewController.m
- (id)initWithImage:(UIImage *)image
{
UIImageView * imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"nameoffile.jpg"]];
self.image = image;
[image release];
}
But no luck. It won't let me link my UIImage instance in the xib.
Try to use this one.You know you can't get IBOutlet on UIImage. So you need to write UIImageView instead of UIImage.
#property(nonatomic,retain) IBOutlet UIImageView* image ;
As the UIImageView is created when the NIB file is loaded, there is no need to make it an instance variable, so remove it from your header file:
UIImageView *image;
Next ensure that your UIImageView outlet is actually connected correctly to the image view within the NIB file. You will see a filled circle when it is connected (this is from a Beginning iOS Development example, which uses ARC, so ignore the weak keyword):
And finally you should be able to set the image view's image in the viewDidLoad method (there is no need to use an instance variable for the UIImage either, as it will be retained within the UIImageView):
- (void)viewDidLoad
{
[super viewDidLoad];
imageView.image = [UIImage imageNamed:#"nameoffile.jpg"];
}
Check the Error of your code.
#property(nonatomic,retain) UIImageView *imageView;
#property(nonatomic,retain)UIImage* image ;
- (id)initWithImage:(UIImage *)image
{
_imageView = [[UIImageView alloc] initWithImage:image];
_imageView.frame=self.view.frame;
[self.view addSubView:_imageView];
[image release];
}
we are doing a photo application in which UIImagePickerController is used. For maintaining only one instance of the controller we have declared it in the appdelegate. But even after doing that memory leak is still there. Can any one please help us
Here's our code
In AppDelegate.h
UIImagePickerController *imagePicker;
#property (nonatomic, retain) UIImagePickerController *imagePicker;
In AppDelegate.m
#synthesize imagePicker;
and in applicationDidFinishLaunching event
imagePicker = [[[UIImagePickerController alloc] init] autorelease];
Need to call this UIImagePicker in CameraView
In CameraView.h
RedDawnMediaAppDelegate *appDel;
#property (nonatomic, retain) RedDawnMediaAppDelegate *appDel;
In CameraView.m
#synthesize appDel;
and in viewDidLoad
appDel=(RedDawnMediaAppDelegate*)[[UIApplication sharedApplication] delegate];
appDel.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
// Hide the camera controls:
appDel.imagePicker.showsCameraControls = NO;
appDel.imagePicker.navigationBarHidden = YES;
appDel.imagePicker.delegate = self;
// Make the view full screen:
appDel.imagePicker.wantsFullScreenLayout = YES;
appDel.imagePicker.cameraViewTransform = CGAffineTransformScale(appDel.imagePicker.cameraViewTransform, CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);
// Now incert our overlay view (it has to be here cuz it's a modal view):
appDel.imagePicker.cameraOverlayView = overlayView;
[self presentModalViewController:appDel.imagePicker animated:YES];
in didFinishPickingMediaWithInfo
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[appDelegate.imagePicker dismissModalViewControllerAnimated:YES];
uploadImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[uploadImage retain];
NSData *imageData = UIImageJPEGRepresentation(uploadImage, 0.5);
//[uploadImage release];
UIImage *image=[UIImage imageWithData:imageData];
self.view.frame = CGRectMake(0, 0, 320, 480);
self.wantsFullScreenLayout = YES;
objCameraImageView = [[CameraImageView alloc] initWithNibName:#"CameraImageView" bundle:[NSBundle mainBundle]];
[objCameraImageView setParentController:self];
objCameraImageView.cameraImage = image;
[image release];
uploadImage = nil;
[self.view addSubview:objCameraImageView.view];
[self release];
}
After taking a photo we are showing the preview in another view. so we are invoking the Cameraview for several times which is leading to Memory leak pls help.
First of all you dont need to worry about maintaining only one instance of imagepickercontroller. Getting an image from camera is much simpler than what you are doing.
See my post here:
How to take picture from Camera & saved in Photo Gallery by programmatically?
since Im releasing the picker when its done getting the image. There wont be memory leak!
I have the following code:
#interface NeighborProfileViewController : UIViewController {
UIImageView * profPic;
UITextView * text;
UIButton * buzz;
NSString * uid;
NSMutableData *responseData;
NSDictionary * results;
}
#property (nonatomic, retain) IBOutlet UIImageView * profPic;
#property (nonatomic, retain) IBOutlet UITextView * text;
#property (nonatomic, retain) IBOutlet UIButton * buzz;
#property (nonatomic, retain) NSString * uid;
#end
Here's what I have in the viewDidLoad on the .m file
#implementation NeighborProfileViewController
#synthesize uid;
#synthesize profPic;
#synthesize buzz;
#synthesize text;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = //some URL to the picture;
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
self.profPic = [[UIImageView alloc] initWithImage: img];
}
I think I wired up the UIImageView via IB correctly. I have an outlet from the UIImageView to the profPic in the Files Owner. What am I doing wrong?
If you are setting a default image is that staying visible after you call self.profPic = [UIImageView] or is it being removed from the screen?
I think this problem comes when self.profPic releases the old image view to replace it with the one you've just created. The old UIImageView instance, along with all the properties which you defined in IB, are probably automatically removed from the superview. Which is why you're not seeing the downloaded image.
If you used IB to create the UIImageView then you don't want to create a new ImageView and assign it to profPic (which is already a fully instantiated UIImageView). Try calling [profPic setImage:img]; which will just change the image in the profPic imageview.
#Equinox use
[profPic setImage:img];
instead of
self.profPic = [[UIImageView alloc] initWithImage: img];
although using autorelease is not an issue here.
you can also do something like this
UIImage *img = [[UIImage alloc] initWithData:data] ;
[profPic setImage:img];
[img release];
the problem with
self.profPic = [[UIImageView alloc] initWithImage: img];
is that you are now creating another memory location for profPic and that means profPic will no longer point to the UIImageView in your IB any more