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.
Related
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.
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];
}
I have been trying for days to get this code to work, but I have no idea what I am doing wrong. Everytime the app wakes up from sleep, or the user closes the app and opens it again (without closing the app from multitasking), I want a label value to change.
In my applicationDidBecomeActive, I am running a counter, which I want to display on whatever viewcontroller is open at that moment.
Code:
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel];
}
In my viewcontroller W1G1, I have the following code:
Code:
- (void) setlabel {
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
I have imported W1G1 in my appdelegate, but the code does not run :( Please help!
Thanks
In the AppDelegate.m file, where you have
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel];
}
the variable counter being incremented is confined to the AppDelegate. In other words, your view controller doesn't know that it has been incremented.
I would suggest that you use NSUserDefaults to store the value of counter so that you can easily pass it between these view controllers. Either that, or you could allow for an input into the method setLabel, e.g.
- (void) setlabel:(int)counter {
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
and then in the AppDelegate you'll want to do:
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel:counter]; // <-- now you're using counter
[self.window addSubview:view1];
}
1) When you say 'the code does not run' do you mean that? That is, if you put NSLogs in applicationDidBecomeActive: and in setLabel does it show the code is run?
2) I would suspect the code is running. But your code won't "show the counter on whatever view controller is open at that moment". Your code creates a new view (view1), but that view won't be displayed. It is not added as a subview to anything. Your code will also leak. You create a W1G1 object, but it is never released and you throw away any reference you have to it.
To achieve what you want, you could add a subview to the application's window. Depending how your app delegate is set up, something like the following should do the trick:
counter++;
W1G1 *viewController1 = [[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil];
[viewController1 setlabel: counter];
[[self window] addSubview: [viewController1 view]]
// you'll want to save a reference to the viewController somehow so you can release it at a later date
Then in W1G1
- (void) setlabel: (int) counter;
{
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
There are, of course, lots of other approaches you could take towards this problem. And you'll need some strategy for removing the W1G1 view that you are adding at some stage, otherwise you'll just get more and more views added.
Update: You ask (in comments) how to keep track of your viewController throughout lifetime of the app... One approach is to keep track of it in your appDelegate. In the header have something like:
#class W1G1;
#interface MyAppDelegate : : NSObject <UIApplicationDelegate>
{
// other decelerations
int counter;
W1G1 * _myW1G1
}
#property (nonatomic, retain) W1G1* theW1G1
In the .m file include
#synthesize theW1G1 = _myW1G1;
Probably in application:didFinishLaunchingWithOptions: create the viewController, set the property to refer to it, and add its view to the view hierarchy.
W1G1* theViewController = [[W1G! alloc] initWithNibName: #"W1G1" bundle: nil];
[[self window] addSubview: [theViewController view]];
[self setTheW1G1: theViewController];
[theViewController release];
Then when you want to access the viewController again from with the app delegate use [self theW1G1], e.g.
[[self W1G1] setlabel: counter];
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.
I have a small application for displaying several UIImageViews in a UIScroller in a similar fashion to the Photo app. I have a TableView which, when i select an item, parses an XML document of photos (added to an array) and adds a UIViewController which displays the images.
The problem is I have a tab bar controller which, upon clicking a tab bar item should go back to the TableView after remove the View that displays the images and dealloc all used memory. The problem is I can't work out how to achieve this. Whether it's a lack of understanding the memory rules I don't know.
Here's the process I'm having issues with.
Table View Controller
This is called after parserDidEndDocument:. backToMenu is called from the tab bar item.
#interface AlbumsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
AlbumViewController *albumViewController;
}
#property (nonatomic, retain) AlbumViewController *albumViewController;
- (void)displayPhotos {
albumViewController = [[AlbumViewController alloc] initWithNibName:#"AlbumView" bundle:nil];
albumViewController.parentView = self;
albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;
[self.view addSubview:albumViewController.view];
[albumViewController populateScroller];
}
- (void)backToMenu {
[albumViewController.view removeFromSuperview];
}
Album View Controller
This is a UIViewController containing a UIScroller and UIPageControl. It adds several ImageViewControllers.
- (void)populateScroller {
imagesScroller.pagingEnabled = YES;
imagesScroller.contentSize = CGSizeMake(imagesScroller.frame.size.width * [self.arrPhotos count], 380);
imagesScroller.showsHorizontalScrollIndicator = NO;
imagesScroller.showsVerticalScrollIndicator = NO;
imagesScroller.scrollsToTop = NO;
imagesScroller.delegate = self;
imagesScroller.backgroundColor = [UIColor blackColor];
pageControl.numberOfPages = [self.arrPhotos count];
pageControl.currentPage = 0;
pageControl.backgroundColor = [UIColor blackColor];
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.arrPhotos count]; i++) {
CGRect frame = imagesScroller.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
NSString *strImagePath = [self.arrPhotos objectAtIndex:i];
ImageViewController *imageViewController = [ImageViewController alloc];
imageViewController.localImage = YES;
[imageViewController initWithPhotoName:strImagePath];
[controllers addObject:imageViewController];
imageViewController.view.frame = frame;
[imagesScroller addSubview:imageViewController.view];
[imageViewController release];
}
self.viewControllers = controllers;
[controllers release];
}
ImageViewController
This has one method. It adds an subclassed UIView called ImageView which handles adding a UIImageView.
- (void)loadImage {
NSString *strRootURL = #"http://www.marklatham.co.uk";
CGRect rect = CGRectMake(0.0, 0.0, 320.0, 480.0);
ImageView *imageView = [ImageView alloc];
imageView.strURL = [strRootURL stringByAppendingString:self.strThisPhoto];
imageView.strTmpPrefix = (self.localImage) ? #"_tmp_rockphotothumb_" : #"_tmp_rockphotolarge_";
[imageView initWithFrame:rect];
[self.view addSubview:imageView];
[imageView release];
}
The backToMenu function is supposed to remove/dealloc AlbumViewController and call delloc on ALL child subviews freeing up the used memory.
Where am going wrong? Any help would be appreciated.
Thanks.
Your AlbumViewController is still holding a reference to the view, so it won't get released until you release that reference. But, this is a good thing.
Don't worry about freeing memory every time the user changes screens. It'll just slow things down as they flip back and forth between different views. If the system gets low on memory, it'll call didReceiveMemoryWarning on all of your view controllers, which will cause them to release their views if they aren't being displayed.
You just want to be a bit more clever about how you allocate/release the albumViewController
- (void)displayPhotos {
////// Only create this view controller if it doesn't exist yet
if(albumViewController == nil) {
albumViewController = [[AlbumViewController alloc] initWithNibName:#"AlbumView" bundle:nil];
}
albumViewController.parentView = self;
albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;
[self.view addSubview:albumViewController.view];
[albumViewController populateScroller];
}
- (void)backToMenu {
[albumViewController.view removeFromSuperview];
//// if you don't do this, you'll have a retain cycle between the two
//// view controllers and neither will ever get released
albumViewController.parentView = nil;
}
- (void)didReceiveMemoryWarning {
///// if the albunViewController isn't in use, go ahead and free its memory
if([self.albumViewController isViewLoaded] && self.albumViewController.view.superview == nil) {
self.albumViewController = nil;
}
[super didReceiveMemoryWarning];
}
Also, instead of calling populateScrollers from AlbumsViewController, call it in the setArrPhotos method of AlbumViewController, but only if arrPhotos has changed. For example:
- (void)setArrPhotos:(NSArray *)newArrPhotos {
if(newArrPhotos != arrPhotos)
{
[arrPhotos release];
arrPhotos = [newArrPhotos retain];
[self populateScrollers];
}
}
This way, if the user goes to view the same album over and over again, you won't recreate the same view hierarchy over and over.
After convincing my client I managed to get around this by going with the three20 framework.