IBAction to set UIImageview image in second View Controller? - iphone

I am trying to set up something where the IBAction from view controller 1 would set the ImageView image in View Controller 2's viewDidLoad using tags to differentiate between the buttons pressed.... Something like (not exact code...just hashing it out in my head):
In View Controller 1:
-(IBAction)buttonpressed:(id)sender {
if (button.tag == 1) {
ViewController2ImageView.image = [UIImage imageNamed:#"image1.png"];
}else if (button.tag == 2) {
ViewController2ImageView.image = [UIImage imageNamed:#"image2.png"];
}
In View Controller 2:
-(void)viewDidLoad {
ViewController2ImageView.image = [UIImage imageNamed:#"?.png"];
}
The issue would be how to get the info from the IBAction to pass to the second view controller and having the viewDidLoad method load the correct image.
Ive seen examples converting data to NSString and passing it that way however I was really wondering if there was a better way to go about this.
Ive been able to Google my way through putting a few apps together so far however this has had me scratching my head for a few days now.
Any help or suggested code would be helpful! Even if its just a push in the right direction.
Thanks!

When the button is pressed in viewController1, do something like this:
-(IBAction)buttonpressed:(id)sender {
if (button.tag == 1) {
[[NSUserDefaults standardUserDefaults] setObject:#"image1.png"
forKey:#"viewController2SelectedImageKey"];
} else if (button.tag == 2) {
[[NSUserDefaults standardUserDefaults] setObject:#"image2.png"
forKey:#"viewController2SelectedImageKey"];
} else {
//set some default string for the image
[[NSUserDefaults standardUserDefaults] setObject:#"yourDefaultImage.png"
forKey:#"viewController2SelectedImageKey"];
}
}
Then in your viewDidLoad method in viewController2 do something like this:
- (void)viewDidLoad {
ViewController2ImageView.image = [UIImage imageNamed:[[NSUserDefaults
standardUserDefaults] objectForKey:#"viewController2SelectedImageKey"]];
//other setup
}
This code sets a string to a key in the NSUserDefaults plist (the key I used is #"viewController2SelectedImageKey" but you can use any string you like), which is referenced by viewController2 upon its viewDidLoad method and uses the string as the name of the image file.

Why not use a NSString *imageName property to pass the filename to View Controller 2?

Hi You can do simply with many type as below
1)you can write the method
(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle )nibBundleOrNil andImageName:(NSString)ImageName;
write this mehod in the second view & call from the first view and when this method call at that time store this image name in the second local variable like below
(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle )nibBundleOrNil andImageName:(NSString)ImageName
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
//Local Variable Assignment
imageName=ImageName;
}
return self;
}
and then pass it in ur code means in ur
(void)viewDidLoad {
ViewController2ImageView.image = [UIImage imageNamed:imageName];
}
2)Second type is create imageName Varibale in the secound view and give #property and #synthesize it and than use it at below
SecoundView *ObjSecoundView=[[ObjSecoundView alloc] initWithNibName:#"SecoundView" bundle:nil];
ObjSecoundView.imageName=#"Image1.png";//put ur dynamic image name
[self.navigationController pushViewController:ObjSecoundView animated:YES];
pass this and use in the viewdid load method as below
(void)viewDidLoad {
ViewController2ImageView.image = [UIImage imageNamed:imageName];
}

Related

Sharing UIImageView between View Controllers in TabBar

I have a UITabBarController based app. I've made a masterVC Class, all ViewControllers that make up the tabBarController are subclasses of the masterVC. I want to set an UIImageView (which is a property of masterVC) that once set shows that image on each view within the tabBarController.
If I was instantiating each VC I could pass the image as a property (this would be simple). However, there's no method to do this between tabBarController ViewControllers.
The easiest conceptual example of what I'm trying to do is by this example in each view Controller within the tabBarController. There has to be a better way:
-(void)viewDidAppear:(BOOL)animated
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:kMainImageData];
if (data) {
self.mainImageView.image = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
}
-(void)viewWillDisappear:(BOOL)animated
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.mainImageView.image];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:kMainImageData];
}
Well there is, create a proper data source, where each UIViewController can request data. There are some ways:
Save the image to disk, use a helper class to retrieve it.
Save the image as property of a Singleton and retrieve it.
You could overload the method
-(id) initWithCoder:(NSCoder*)aDecoder
With something like this:
self = [super initWithCoder:aDecoder];
if ( self )
{
static UIImage *reuseImage = nil;
if ( reuseImage == nil )
{
//Init reuseImage with your image
}
myImageViewProperty.image = reuseImage;
...
return self;
If I'm understanding you correctly, I think you can do this all in your superclass with key-value observing.
In your masterVC header, declare:
#property (strong) UIImage *sharedImage;
And in the implementation:
#synthesize sharedImage;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self addObserver:self forKeyPath:#"sharedImage" options:NSKeyValueObservingOptionNew context:NULL];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"sharedImage"]) {
self.mainImageView.image = self.sharedImage;
}
}
- (void)dealloc {
[self removeObserver:self forKeyPath:#"sharedImage"];
}
Then, whenever the sharedImage property is set on any of the subclasses, your image view will update its contents accordingly.
I think the easiest thing would be to move the viewDidAppear method you posted into your masterVC class. Then in your ViewControllers that subclass masterVC you can:
Remove the viewDidAppear method if you have no other setup to do, it will then call the viewDidAppear that is in your masterVC.
OR
Change viewDidAppear to the following so that it will call viewDidAppear in masterVC then do all your other setup.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// your other code...
}

Access/Reference imageView.image to replace it later

Alright, this has been driving me insane for the last few days. I hope this is an easy fix. I am trying to access my UIImageView.image so I can replace it later.
With only the needed code here it is:
I first create an imageView for each time a user clicks on a photo in their Library.
// .h
#property (strong,nonatomic) UIImage *doneImage;
#property (strong,nonatomic) UIImageView *editImage;
// .m
#synthesize doneImage;
#synthesize editImage;
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(xCoordinate, yCoordinate, widthOfImage, heightOfImage)];
imgView.image = originalImage;
imgView.userInteractionEnabled = YES;
[self.mainView addSubview:imgView];
// I add gestures
longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 1;
longPress.numberOfTouchesRequired = 1;
[imgView addGestureRecognizer:longPress];
}
When someone clicks holds down on one of those images this pops up
- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer {
editImage = (UIImageView*)recognizer.view; // I declare what editImage is and now have access to what imageView is being interacted with.
doneImage = editImage.image; // I then get the image of that for later use.
if(UIGestureRecognizerStateBegan == recognizer.state) {
popoverEditor = [[UIPopoverController alloc] initWithContentViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"popupEditor"]];
[popoverEditor presentPopoverFromRect:editImage.bounds inView:editImage permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
This pops up a menu with 4 buttons. I then have an IBAction that tries to fire up the editing part.
- (IBAction)effectsEditorButton:(id)sender {
// editImage is my imageView
if (editImage == nil) {
NSLog(#"imageView was nil wtf");
} else {
[self performSelector:#selector(editImageWithEffects:)];
}
}
My image view is ALWAYS nil. I need to get a reference to that somehow. I've tried tags but I can't seem to get them to hold their value once I get to this point.
Any help would be very much Appreciated. Thanks!
Are you leaving out code? Based on what you have here, editImage will always be null because it isn't declared anywhere (perhaps something in Interface Builder that we can't see?).
You need a way to link back into your view controller from your popover. Popular ways to do this are to use a completion block when returning from your popover controller, or setting your "main" VC as a weak property on the popover.

UIImage VIew Not loading image?

I have a UIImage on my MyCartViewController. And i have a button on my BlackFacePlatesViewController. I want this button to set the image on the MyCartViewController to another image, however i can't seem to get it to work. Here is my code for the button to set the image on the MyCartViewController:
EDIT:
I HAVE 1 BOOL VARIABLE IN VC2 AND WHEN THE BUTTON IS PRESSED IN VC1, I SET THE BOOL AND CREATE VC2. THEN IN THE VIEWWILLAPPEAR METHOD, I SET THE IMAGE ACCORDINGLY. HERE IS THE CODE: THANKS
- (IBAction)outlet1 {
MyCartViewController * imageCart = [[MyCartViewController alloc]init];
imageCart.displayImage = YES;
}
BUTTON THAT THE USER PRESSES ^
THIS IS TO SWITCH PAGES:
- (IBAction)myCart:(id)sender; {
MyCartViewController * first = [[MyCartViewController alloc]init];
first.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:first animated:YES];
[first release];
}
THIS IS THE VIEWWILLAPPEAR METHOD IN VC2:
-(void)viewWillAppear:(BOOL)animated{
if (self.displayImage == YES) {
UIImage * myImage = [UIImage imageNamed:#"Paddle_3.png"];
[outletImageView setImage:myImage];
}
}
WOULD THIS WORK? THANK YOU VERY MUCH FOR THE HELP EVERYBODY!!!
You aren't allocating your object cart properly, and cart2 has nothing to do with cart, apart from being a similar class. You should just make an instance variable in the header file that's a UIImage which holds the image you want to use in your next UIView, and set it when you use presentModalViewController: Try this. In your .h file,
#interface MyCartViewController : UIViewController {
UIImage * imageForNextView;
}
In your .m file,
- (IBAction)outlet1:(id)sender; {
imageForNextView = [UIImage imageNamed:#"Paddle_1.png"];
}
- (IBAction)outlet2:(id)sender; {
imageForNextView = [UIImage imageNamed:#"Paddle_2.png"];
}
- (IBAction)myCart:(id)sender; {
MyCartViewController * cart2 = [[MyCartViewController alloc]init];
cart2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cart2.newImage.image = imageForNextView;
[self presentModalViewController:cart2 animated:YES];
[cart2 release];
}
I made 2 button methods to illustrate the point of switching the image based on which button was pushed. Remember that imageNamed: caches the UIImage, so if you have a lot, you may have to start looking into other loading methods, all of which can be found here. This should solve your problem.
Edit: Try this. In your .h file,
#interface MyCartViewController : UIViewController {
NSString * nameOfImage;
UIImageView * imageView;
}
#property (nonatomic, retain) NSString * nameOfImage;
In the .m file,
#synthesize nameOfImage;
- (void)viewDidLoad; {
[super viewDidLoad];
imageView.image = [UIImage imageNamed:nameOfImage];
}
Then, when you push to the view, try:
- (IBAction)myCart:(id)sender; {
MyCartViewController * cart2 = [[MyCartViewController alloc]init];
cart2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cart2.nameOfImage = #"Paddle_2.png";
[self presentModalViewController:cart2 animated:YES];
[cart2 release];
}
Edit2: This is a tutorial about how to use a UISplitViewController, which has a similar idea, where you press a UITableViewCell, and it changes an image in another UIView. You should look through this, and see if it can help your project.
Also, try:
- (IBAction)myCart:(id)sender; {
MyCartViewController * cart2 = [[MyCartViewController alloc]init];
cart2.nameOfImage = #"Paddle_2.png";
[self pushViewController:cart2 animated:YES];
[cart2 release];
}
This is another way to move to a new UIView, which may work.
Hope that Helps!
Are you sure this line of code is actually executed? Did you check that while debugging or with an NSLog?
If not then check the reference to the action 'outlet1'.
What is cart?
What is cart.newimage?
How are those linked to the UIImagaeView that is part of 'the next page'?
You may need to force the redraw via setNeedsDisplay.
Assuming your cart.newImage is the UIImageView object:
[cart.newimage setNeedsDisplay]; //might do the trick.
However, that is a bit view of code to really understand the issue.

viewDidLoad method not being called using presentModalDialog method

I am using presentModalDialog to show a viewcontroller's view however the viewDidLoad never gets called?!
Is there any method that is called where I can place my logic that fills and configures the view?
EDIT:
It's a bit difficult to put a small amount of code, you kind of need to see it all, but here goes:
I have 2 nibs and 2 view controllers (portrait-mainvc/landscape) which both inherit from 1 baseclass which has the logic and the iboutlets. This is to allow me to re-use code. When the orientation changes in the main controller, it switches between the 2 controllers (modal dialog) which in turn use their respective nib's however they all use the same base code to configure the UI items.
#implementation HomeViewControllerBase
- (void)configureBestSellItems
{
[self startRetrievingRegions];
// load all the images from our bundle and add them to the scroll view
// NSUInteger i;
for (int i = 0; i <= 150; i++)
{
NSString *imageName = #"tempImage.jpg";
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[self.bestSellScrollView addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureBestSellItems];
}
#end
#interface HomeViewController : HomeViewControllerBase
{
}
#interface HomeViewController_Landscape : HomeViewControllerBase
{
}
#implementation HomeViewController
//This works for portrait
- (void)viewDidLoad
{
[super viewDidLoad];
}
#end
#implementation HomeViewController_Landscape
//This does not work
- (void)viewDidLoad
{
[super viewDidLoad];
}
//This works as suggested
- (void)awakeFromNib
{
[super configureBestSellItems];
}
#end
You can try these in your viewcontroller:
-(void)awakeFromNib
{
[super awakeFromNib];
// your code here
}
or
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// your code here
}
However, you should try to find why viewDidLoad is never called. You can also check this
link.
You may have a custom function in there named presentModalDialog:, as searching apple's docs doesn't have that function. You're calling a custom function that loads a Xib.
I'm doing the same thing.
You want this:
[self presentModalViewController:controller...
ViewDidLoad is called by Controllers, if the awakeFromNib is being called, you're probably getting, by itself, the view.
It's a common problem in objective c:
you should review the flowing:
1-initiation of the view controller you should initialize it in the right way in app delegate.
2-review the file owner of the view it must be the right class which usually the same name of uiview.

Dynamically load nib for iPhone/iPad within view controller

I have converted an iPhone application using the wizard like thing in XCode into a universal app.
It builds fine but obviously looks a bit rubbish in some areas :)
I need to load nibs according to which device is being used. I dont wish to create my view controllers using initWithNib as I already have code to create the controllers with some data (initWithMyLovelyData) which doesnt do anything to do with nib loading.
I know to find out the device you use UI_USER_INTERFACE_IDIOM() so I tried overriding the initWithNibName within the actual view controllers themselves, assuming they get called internally somehow. But it's not working as I guess I am unsure of the syntax.
I have tried
if(ipad..) self = [super initWithNibName:#"MyIpadNib" bundle:nibBundleOrNil];
And that doesnt work :/
EDIT - I know I have massively edited this, made my question a bit more specific after doing some more research - apologies!
Actually, Apple does all this automatically, just name your NIB files:
MyViewController~iphone.xib // iPhone
MyViewController~ipad.xib // iPad
and load your view controller with the smallest amount of code:
[[MyViewController alloc] initWithNibName:nil bundle:nil]; // Apple will take care of everything
EDIT: #Adam's answer below is the correct answer.
To determine which nib to load, do the following, and scrap your initWithMyLovelyData method and use a property to set the data. You should be able to easily move all your init code into the property setter method.
MyViewController *viewController;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
viewController = [[MyViewController alloc] initWithNibName:#"ipadNIB" bundle:nil];
} else {
viewController = [[MyViewController alloc] initWithNibName:#"iphoneNIB" bundle:nil];
}
viewController.myLovelyData = someData;
I just put these two methods in a class called IPadHelper, and use the addIPadSuffixWhenOnIPad method to conditionally pick between two nibs depending on platform
+ (BOOL)isIPad{
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2){
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
return YES;
}
}
return NO;
}
+ (NSString *)addIPadSuffixWhenOnIPad:(NSString *)resourceName{
if([IPadHelper isIPad]){
return [resourceName stringByAppendingString:#"-iPad"];
}
else {
return resourceName;
}
}
see here http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html for more explanation of the first method...
You can have your cake and eat it too. Just add a method that wraps initWithNibName:bundle: and adds your myLovelyData parameter:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil myLovelyData:(id)data
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]))
{
// Custom initialization using myLovelyData
//
}
return self;
}
I think it will be better to create C file.
FileHelper.h
#import <Foundation/Foundation.h>
BOOL isIPad();
NSString *addIPadSuffixWhenOnIPad(NSString *resourceName);
FileHelper.m
#import "FileHelper.h"
BOOL isIPad() {
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2) {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
return YES;
}
}
return NO;
}
NSString *addIPadSuffixWhenOnIPad(NSString *resourceName) {
if(isIPad()) {
return [resourceName stringByAppendingString:#"-iPad"];
}
else {
return resourceName;
}
}