I want to get the UIImage out of CGContextRef, and show it on UIImageView in a different UIViewController
So for this, I have written this code, I m writing this code, when I close my drawingview, because I have made my drawing view as a subview of UIViewController
//mydrawingView.m
- (void)closeButtonClicked
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO,0.0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
m_curImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
ViewController *table = [[ViewController alloc] init];
[table setImage:m_curImage];
[table viewDidLoad];
}
///myViewController.h
#interface ViewController : UIViewController
{
IBOutlet UIImageView *m_imageView;
UIImage *image;
}
#property(nonatomic, strong) UIImage *image;
///myViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
m_imageView.image = image;
NSLog(#"%#", m_imageView.image);
}
But I am not able to show this image on UIImageview,
Regards
Ranjit
I have sorted out the answer for this question, to get the image out of the canvas , the above code applies and to show it on a imageView of anotherViewController, we have to implement delegate protocol method.
Regards
Ranjit
Related
I am building a simple application to show images.
I send the image url, and it should be downloading.
This is my code:
#import "ImageViewController.h"
#interface ImageViewController ()
#property (nonatomic, strong) UIImageView * imageView;
#property (nonatomic, strong) UIImage * image;
#end
#implementation ImageViewController
-(void)setImageURL:(NSURL *)imageURL{
_imageURL = imageURL;
self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
}
-(UIImageView*)imageView{
if(!_imageView)
return [[UIImageView alloc]init];
return _imageView;
}
-(UIImage*)image{
return self.imageView.image;
}
-(void)setImage:(UIImage *)image{
self.imageView.image = image;
[self.imageView sizeToFit];
}
-(void)viewDidLoad{
[self.view addSubview:self.imageView];
NSLog(#"Image Url = %#", self.imageURL);
}
#end
I call it like this:
if ([segue.destinationViewController isKindOfClass:[ImageViewController class]]){
ImageViewController* ivc = (ImageViewController*)segue.destinationViewController;
ivc.imageURL = [[NSURL alloc]initWithString:[NSString stringWithFormat:#"http://images.apple.com/v/iphone-5s/gallery/a/images/download/%#.jpg", segue.identifier]];
I am 100% sure that the passed url is correct because I already check that through debugging
The image is absolutely being downloaded because its size is large and the screen is blocking while downloading it.
The problem is the that imageView doesn't show it after finishing downloading.
Could u help me please?
Edit
The header file
#import <UIKit/UIKit.h>
#interface ImageViewController : UIViewController
#property(nonatomic, strong) NSURL* imageURL;
#end
This is all my code, so you can test it if you want.
Edit2
I have a scroll view, maybe that is the problem ?
Please check the image
You have an issue in the getter of the imageView property. You are not initialising the attribute, but returning a different object each time. Replace the line:
return [[UIImageView alloc]init];
by
_imageView = [[UIImageView alloc]init];
Please try to edit your code as following it is working for me, in your case problem may be because you are passing url from different view controller that you are :
[self.imageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://images.apple.com/v/iphone-5s/gallery/a/images/download/photo_1.jpg"]]]];
You can check from attached screen shot..
Set the imageView's frame instead of sending sizeToFit method.
-(void)setImage:(UIImage *)image{
self.imageView.image = image;
// [self.imageView sizeToFit];
self.imageView.frame = CGRectMake(100.0, 100.0, image.size.width, image.size.height) ;
}
Edit :
I see there is a scrollView on 'self.view', so it may block self.imageView, try to bring it to front using [self.view bringSubviewToFront:self.imageView] ; if you want it be the topmost of all subView on self.view.
You are not assigning you newly created imageView to your _imageView. So every time it triggers imageView method, it returns a new UIImageView. try this...
- (UIImageView*)imageView
{
if(!_imageView) {
_imageView = [[UIImageView alloc]init];
return _imageView;
}
return _imageView;
}
I have been struggling with coding up a very simple app that launches and shows an image. The image is set programatically.
The steps I have tried:
Create empty application
Add ViewController & wire to AppDelegate
Add UIImageView
Set image.
I have code that doesn't work in a previous question:
Get UIImage to show in UIImageView
But that path did not work. If someone could outline the golden path of what I need to do I would be grateful.
#import "ViewControllerSimple.h"
#interface ViewControllerSimple ()
#end
#implementation ViewControllerSimple
- (void)viewDidLoad
{
[super viewDidLoad];
//Creat an image:
UIImage *image = [UIImage imageNamed: #"someImage.png"];
//Creat UIImageView:
UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
//Set its frame:
[imageView setFrame:CGRectMake(0, 0, 300, 300)];
//Add to your view:
[self.view addSubview:imageView];
}
#end
Is this what your looking for? or the AppDelegate is the problum? or creating a UIViewController?
Say I'm adding a UIImageView, and I want to dissolve it in so instead of appearing sharply it's a little more smooth to show up. Is this possible?
As outlined in this answer, you can dissolve changes as so:
UIImage * toImage = [UIImage imageNamed:#"myname.png"];
[UIView transitionWithView:self.imageView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
} completion:nil];
Just curious if additions can receive similar treatment.
Your code will do what you want,Just have a try with the code below:
(Btw: don't call transitionWithView: in viewDidLoad:,animation for imageView not work in viewDidLoad)
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (strong,nonatomic) UIImage * imageOne;
#property (strong,nonatomic) UIImage * imageTwo;
#end
#implementation ViewController
- (void)viewDidLoad
{
self.imageOne = [UIImage imageNamed:#"a.jpg"];
self.imageTwo = [UIImage imageNamed:#"b.jpg"];
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//init imageView here
if(self.imageView.image == nil){
[self performSelector:#selector(handleButtonTouch:) withObject:nil afterDelay:1];
}
}
- (IBAction)handleButtonTouch:(id)sender {
UIImage * toImage = ([self.imageView.image isEqual:self.imageOne]) ? self.imageTwo : self.imageOne;
[UIView transitionWithView:self.imageView
duration:3.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
}
completion:NULL];
}
#end
Try adding a completely blank image initially, and then change it to the image of your choice - that will give you the "dissolve animation on addition" feel you want.
I have three images that I want to rotate in the background. Below is what I have so far. I want to have a class where I can hold all these UIImageViews and display them randomly in the background. I read about UIView and the frame method but I have no idea how to add them since it only takes in one frame.
Thus, I used NSArray to hold all the objects instead. The only problem now is when a new background appears, the old background doesn't disappear. Now do I remove the old background?
It would be great if someone can point me in the right direction.
Thanks!
#interface ViewController : UIViewController
#property (strong, nonatomic) NSArray *imageArray;
#property (strong, nonatomic) UIImageView *imageView;
- (IBAction)buttonPressed:(UIButton *)sender;
#end
// .m file
#implementation ViewController
#synthesize imageArray;
#synthesize imageView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
imageView = [[UIImageView alloc] init];
UIImage *image1 = [UIImage imageNamed:#"image1.png"];
UIImage *image2 = [UIImage imageNamed:#"image2.png"];
UIImage *image3 = [UIImage imageNamed:#"image3.png"];
imageArray = [[NSArray alloc] initWithObjects:image1, image2, image3, nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonPressed:(UIButton *)sender {
NSUInteger index = arc4random_uniform(self.imageArray.count);
[imageView setImage:[imageArray objectAtIndex:index]];
}
#end
This:
[self.view insertSubview:current atIndex:0];
Is adding another view to your view hierarchy, but you are not removing the one you previously placed. So you have an ever-growing stack of UIVews. You are also placing the new view at the bottom of the stack.
try
[[[self.view subviews] objectAtIndex:[[self.view subviews] count]-1] removeFromSuperview];
[self.view addSubview:current];
Or better - as #Kaan suggests - have a single UIImageView and simply change it's UIImage property.
To do this, your array will contain your UIImages not your UIImageviews.
Your UIView can be an UIImageview, or it can contain a UIImageview.
The UIImageview has an image property which you can set.
Your code would look something like this...
self.imageArray = [[NSArray alloc] initWithObjects:image1, image2, image3, nil];
NSUInteger index = arc4random_uniform(self.imageArray.count);
UIImage *current;
current = [self.imageArray objectAtIndex:index];
self.imageview.image = current;
In your approach, you have created 6 objects - 3 UIImages and 3 UIImageViews.
What you want can be accomplished using 4 objects instead of 6, using less memory, making your app run more quickly and answering your question at the same time (also, i'm assuming you have background images of all the same size, the size of the device's screen).
I would suggest creating first, only one UIImageView:
//backgroundImage is an IVAR
backgroundImage = [[UIImageView alloc] init];
followed by three UIImages and place them in an NSArray:
UIImage *image1 = [UIImage imageNamed:#"image1.png"];
UIImage *image2 = [UIImage imageNamed:#"image2.png"];
UIImage *image3 = [UIImage imageNamed:#"image3.png"];
//imagesArray is an IVAR
imagesArray = [[NSArray alloc]] initWithObjects: image1, image2, image3, nil];
Finally, to change the background, call the random function and update the UIImageView image property instead of popping a different view on top of the view stack:
NSUInteger index = arc4random() % [imagesArray count];
[backgroundImage setImage:[imagesArray objectAtIndex:index]];
I need to duplicate a view, with all it's subviews.
Does anyone knows how to do it?
The easiest (but probably not the fastest) way is to archive it into an NSData object and unarchive it right away.
NSData *tempArchive = [NSKeyedArchiver archivedDataWithRootObject:myView];
UIView *myViewDuplicate = [NSKeyedUnarchiver unarchiveObjectWithData:tempArchive];
To archive any uiimage object simply convert them to an imagerep of one kind or another (PNG for instance) and archive that NSData object, then in the unarchive you restore the uiimage with imageWithData:
Here is a new method you can use: Use UIView's method:
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
This is the fastest way to draw a view. Available in iOS 7.
One can easily copy a UIView by archiving and unarchiving process.
NSData *tempArchive = [NSKeyedArchiver archivedDataWithRootObject:myView];
UIView *myViewDuplicate = [NSKeyedUnarchiver unarchiveObjectWithData:tempArchive];
But this ignores UIImageView, so for UIImageView do it by this way,
UIImage *img = [UIImage imageNamed: #"myImage"];
UIImage *img2 = [UIImage imageWithCGImage:img.CGImage scale:img.scale orientation:img.imageOrientation];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:img2];
UIImage *imgCopy = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(#"%#, %#", imgCopy, NSStringFromCGSize(imgCopy.size)); // -> <UIImage: 0x7fa013e766f0>, {50, 53}
Refrence from here.
Swift version
This answer shows how to do the same thing in Swift as the accepted answer does in Objective-C.
let tempArchive = NSKeyedArchiver.archivedDataWithRootObject(myView)
let myViewDuplicate = NSKeyedUnarchiver.unarchiveObjectWithData(tempArchive) as! UIView
My full answer with more notes is here.
You can drag your custom view outside the root view of the viewController.
In the implementation of the custom view class, override the enconde/decode methods. Realize the IBOutlets and IBActions connections will not be archived in memory.
#implementation MyCustomView
-(MyCustomView*)aCopy{
NSData *temp = [NSKeyedArchiver archivedDataWithRootObject:self];
return [NSKeyedUnarchiver unarchiveObjectWithData:temp];
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.btnBack forKey:#"btnBack"];
[coder encodeObject:self.lbl1 forKey:#"lbl1"];
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
self.btnBack = [aDecoder decodeObjectForKey:#"btnBack"];
self.lbl1 = [aDecoder decodeObjectForKey:#"lbl1"];
[_btnBack addTarget:self action:#selector(onBtnBack) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (IBAction)onBtnBack{
//. . .
MyCustomView.h:
#import <UIKit/UIKit.h>
#interface MyCustomView : UIView
#property (weak, nonatomic) IBOutlet UILabel *lbl1;
#property (weak, nonatomic) IBOutlet UIButton *btnBack;
-(MyCustomView*)aCopy;
#end
Sample of reusing the custom view in ViewController.m:
#import "ViewController.h"
#import "MyCustomView.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet MyCustomView *myCustomView;
#property (weak, nonatomic) IBOutlet UIView *vwPlaceHolder;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:_myCustomView];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
MyCustomView *vwCopy = [_myCustomView aCopy];
vwCopy.lbl1.text = #"My other msg";
vwCopy.frame = _vwPlaceHolder.frame;
[_vwPlaceHolder removeFromSuperview];
[self.view addSubview:vwCopy];
}
#end