The Problem
I have a UILabel buried in a few layers of subviews and I can't seem to change it's text. The code to update the label is inMyCardSubclass's updateVisualElements method. The really weird thing is that when I log the description of these labels, the text has been updated, but it is not visible. Here's what it looks like:
Inside my View Controller's viewDidLoad method I initialize a UIScrollView and my card object. I add its cardView as a subview like so:
-(void)viewDidLoad
{
[super viewDidLoad];
MyCardSubclass *myCard = [[MyCardSubclass alloc]initWithInfo:info andPoint:CGPointMake(5, runningYValue)];
[myCard setParentViewController:self];
[scrollView addSubview:[myCard cardView]];
//Resize scrollView contentSize
}
My Card
//header
#property (nonatomic, strong) UIView *contentView;
#property (nonatomic, strong) UIView *cardView;
#property (nonatomic, strong) CardInfo *cardInfo;
#property (nonatomic, strong) UIViewController *parentViewController;
//implementaion
-(UIView *)cardView
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIView *toReturn = [[UIView alloc]initWithFrame:CGRectMake(self.point.x,self.point.y, screenRect.size.width-borderOffset*2, cardViewHeight)];
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(borderOffset, 0, toReturn.frame.size.width-borderOffset*2, titleHeight)];
[titleLabel setText:self.title];
[toReturn addSubview:titleLabel];
[self.contentView setFrame:CGRectMake(borderOffset, titleHeight, screenRect.size.width-borderOffset, contentViewHeight)];
if(self.contentView)
[toReturn addSubview:self.contentView];
else
NSLog(#"no contentView");
//other view stuff
return toReturn;
}
My Card Subclass
//header
#property(nonatomic, strong) UILabel *totalAmountLabel;
#property(nonatomic, strong) UILabel *availableAmountLabel;
#property(nonatomic, assign) double available;
//implementation
-(UIView *)cardView
{
[self setContentView:[self contentViewFromCardInfo:self.cardInfo]];
return [super cardView];
}
-(UIView *)contentViewFromCardInfo:(CardInfo *)cardInfo
{
UIView *toReturn = [[UIView alloc]init];
NSString *amount = #"0";
self.totalAmountLabel = [[UILabel alloc]initWithFrame:CGRectMake(labelWidth,
runningYValue,
labelWidth,
labelHeight)];
[self.totalAmountLabel setText:amount];
[toReturn addSubview:self.totalAmountLabel];
runningYValue +=self.totalAmountLabel.frame.size.height+spacer;
self.availableAmountLabel = [[UILabel alloc]initWithFrame:CGRectMake(labelWidth,
runningYValue,
labelWidth,
labelHeight)];
[self.availableAmountLabel setText:#"0"];
[toReturn addSubview:self.availableAmountLabel];
return toReturn;
}
-(void)updateVisualElements
{
NSString *amount = #"10"
NSString *availableString = #100"
//The log descriptions for these labels are okay.
[self.totalAmountLabel setText:amount];
NSLog(#"%#",self.totalAmountLabel.debugDescription);
[self.availableAmountLabel setText:availableString];
NSLog(#"%#",self.availableAmountLabel.debugDescription);
NSAssert([NSThread isMainThread], #"Not on main thread");
NSAssert(self.totalAmountLabel, #"No label");
}
What I've tried
Calling [self.totalAmountLabel setNeedsDisplay] after setting the text
Calling the method on the main thread using [self.totalAmountLabel performSelector:#selector(setText:) withObject:amount afterDelay:0.0]
You can try one thing, Use Tag property to get the added Label and change its contends
Example:
UILabel totalAmountLabel = [[UILabel alloc]initWithFrame:CGRectMake(labelWidth,
runningYValue,
labelWidth,
[totalAmountLabel setText:amount];
totalAmountLabel.tag = 100;
[toReturn addSubview:totalAmountLabel];
Then in your updateVisualElements()
UILabel *tempTotalAmountLabel = (UILabel *)[self.view viewWithTag:100];
[tempTotalAmountLabel setText:amount];
Fixed it! The problem wasn't actually in my attempts to set the label or draw its view.
I wasn't using my initializers properly to init my content view only once.
I removed this override in my subclass
-(UIView *)cardView
{
[self setContentView:[self contentViewFromCardInfo:self.cardInfo]];
return [super cardView];
}
I also took the code from the -(UIView *)cardView method in my superclass and put into a -(UIView *)buildCardView method and rewrote the cardView property accessor to what it should have been.
-(UIView *)cardView
{
if(!_cardView)
_cardView = [self buildCardView];
return _cardView;
}
Thanks for the views and comments.
Related
I have a custom UIView XIB that gets loaded onto my ViewController and the frame is adjusted to be collapsed before added to subview. The UIButton tied to my XIB is showing when the frame is smaller than the button location. How can I hide and show my UIButton as the frame is expanding/collapsing? My XIB is not using AutoLayout.
ViewController.m
self.greenView = [[[NSBundle mainBundle] loadNibNamed:#"Green" owner:self options:nil] objectAtIndex:0];
[self.navigationController.view addSubview:self.greenView];
GreenView.h
#interface GreenView : UIView
#property (weak, nonatomic) IBOutlet UIView *expandView;
#property (nonatomic, getter = isExpanded) BOOL expand;
#property (weak, nonatomic) IBOutlet UIButton *testButton;
- (IBAction)testButtonTapped:(id)sender;
#end
GreenView.m
#interface GreenView()
#property (nonatomic) UITapGestureRecognizer *tapGesture;
#end
#implementation GreenView
- (void)awakeFromNib {
CGRect frame = self.frame;
frame.size.height = self.expandView.frame.size.height;
frame.origin.y = 200;
self.frame = frame;
self.expand = NO;
[self.expandView addGestureRecognizer:self.tapGesture];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (UITapGestureRecognizer *)tapGesture {
if (!_tapGesture) {
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapClicked:)];
}
return _tapGesture;
}
- (void)tapClicked:(UIGestureRecognizer *)recognizer {
CGRect frame = self.frame;
self.expand = !self.expand;
frame.size.height = self.expand ? gvExpandedHeight : gvCollapsedHeight;
[UIView animateWithDuration:0.5 animations:^{
self.frame = frame;
} completion:^(BOOL finished) {
NSLog(#"Frame after animation: %#", NSStringFromCGRect(self.frame));
}];
}
- (IBAction)testButtonTapped:(id)sender {
NSLog(#"Test button tapped");
}
#end
Collapsed:
Expanded:
GreenView.xib:
GrenenView.xib Struts and Springs:
If I understood you just want to clip it, if the button is outside to the view bounds. In -awakeFromNib add:
self.clipsToBounds = YES;
Using this property you are telling the view to cut everything that is not inside its bounds, views caw draw subviews even if they are place outside. Is a little expensive by means of performance, if you use it a lot or during heavy animations.
One way around could be hide it while the view is collapsed.
You change the frame to frame.origin.y = 200;
I think you have to set the UIButton constraint relative to your GreenView in you nib file
I am currently dynamically adding a UIImage to my UIScrollView object and everything is working as intended. I need to add extra functionality now (a UIActivityIndicator in the center of the image when it is loading from the internet, and a label underneath) so I thought why not create a custom View which has all of these laid out as I need them to be, and then just load it into the scrollView. I have encountered a problem though, when I add it to the scrollView, nothing shows up. Here is what I have:
NewsViewController.m:
imageScrollView.contentSize = CGSizeMake(320*numberOfPages, 303);
pageControl.numberOfPages = numberOfPages;
dispatch_queue_t imageDownload = dispatch_queue_create("imageDownload", NULL);
__block NSData *temp;
CustomImageView *customImageView = [[CustomImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 303)];
[imageScrollView addSubview:customImageView];
[[customImageView activityIndicator] startAnimating];
dispatch_async(imageDownload, ^{
temp = [[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.wlfarm.org/wp-content/uploads/2012/05/farm.jpg"]]retain];
dispatch_async(dispatch_get_main_queue(), ^{
customImageView.imageView.image = [[UIImage alloc] initWithData:temp];
[[customImageView activityIndicator] stopAnimating];
[customImageView setNeedsDisplay];
customImageView.caption.text = #"HAHAHAHAHHAHA";
[imageScrollView setNeedsDisplay];
[temp release];
});
});
dispatch_release(imageDownload);
CustomImageView.h:
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UILabel *caption;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m
#import "CustomImageView.h"
#interface CustomImageView ()
#end
#implementation CustomImageView
#synthesize caption, imageView, activityIndicator;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
I am including a screenshot of my XIB file, and the program running on the simulator. The first picture shows nothing in the scrollView(the attempt made by using my custom class), and the second page of the scroll view is the attempt made by adding a UIImageView to the UIScrollView(which worked). Can anyone point out what I am doing wrong? Am I not allowed to load a custom view into a UIScrollView? Thanks for your help!
IB Screenshot - http://i.stack.imgur.com/gz9UL.png
iOS Simulator No Image with CustomView Screenshot - http://i.stack.imgur.com/zhswq.png
iOS Simulator Image with UIImageView Screenshot - http://i.stack.imgur.com/97vmU.png
It looks as though CustomImageView is a subclass on UIViewController, not UIImageView or UIView. You can't add a UIViewController as a subview like that. change it to subclass UIView and it should work.
To load a UIView from a .nib, you need to declare your IBOutlet properties as you would for a UIViewController. Define the correct custom class in IB and connect everything up, including the base view. Then override the following method inside your custom view class.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
It seems you have cut and pasted methods from a UIViewController subclass into you UIView subclass. Start by deleting all the methods you've pasted in between #synthesize and #end . A UIView subclass requires different methods to to load from a .nib, so you need to override the method shown above instead and use the line of code
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
to load the nib.
Further to your comment about connecting the base view, here is what I mean:
After creating your custom class and nib file, open the nib and highlight "Files Owner" on the left, then on the top right hand side, select the icon 3rd from the left, looks like an ID card or something. In the "Class" box, add the name of your custom class.
In your customClass, add an IBOutlet UIView property called baseView, and add a UIView that covers the view in IB at the root level, connect these two. Then add everything else on top of that
you code would now look something like this:
CustomImageView.h
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
IBOutlet UIView *baseView
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) IBOutlet UIView *baseView;
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UILabel *caption;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m
#import "CustomImageView.h"
#interface CustomImageView ()
#end
#implementation CustomImageView
#synthesize baseView, caption, imageView, activityIndicator;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.baseView];
}
return self;
}
#end
Provided you connect it all up in IB it should work fine, just remember to add the baseView
As mentioned earlier initWithNibName belongs to controllers.
As I think, you're going the wrong way.
you have a ViewController and want to add a customView, to load dynamically a image from URLData.
You have 2 Options:
Option 1: Do everything in IB:
In Interfacebuilder edit/(or add a new one) the ViewController's XIB File and add the views that you like. The file's owner is a UIViewController Class/Subclass. Do everything like you did before, except doing it in the view controller. In your App delegate initWithNibName your ViewController like so
self.viewController = [[testViewController alloc] initWithNibName:#"testViewController" bundle:nil];
If you want to, initialize your own view controller, which you like to push and push it in the stack.
What you're doing wrong: You are initializing a customImageView with a Frame, but the nib doesn't get loaded automatically. The Properties are there, but the nib isn't.
If you really want a stable thing choose
Option 2: Do everything programatically (It is easier, more understanding and lightweight):
From your implementation we do the following:
NewsViewController.m
Do like you did before!!!
CustomImageView.h:
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
UIImageView *imageView;
UILabel *caption;
UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) UIImageView *imageView;
#property (nonatomic, retain) UILabel *caption;
#property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
caption = [[UILabel alloc] initWithFrame:CGRectMake(0, 250, 320, 50)];
[caption setBackgroundColor:[UIColor greenColor]];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 250)];
[imageView setBackgroundColor:[UIColor blueColor]];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.frame = CGRectMake(320/2-25, 460/2-25, 50, 50);
[self.activityIndicator startAnimating];
[self addSubview:self.caption];
[self addSubview:self.imageView];
[self addSubview:self.activityIndicator];
}
return self;
}
Then do everything you did before.
That would do a better job
I have a regular UITableViewController and a UITableView as its only view, and I want to have an UIActivittyIndicatorView in addition to the table view.
So I need a view structure like this:
view (UIView):
tableView
activityIndicatorView
What's the cleanest way to do it without InterfaceBuilder? I guess I need to override the loadView: method, but I haven't succeed doing it so far.
UPDATE for ARC and iOS 5.0+ (I think old version needs to be removed already as we have new, better API's:)):
Add to header .h file of your UIViewController subclass:
#property (nonatomic, weak) UIActivityIndicator *activityIndicator;
And override methods in .m file of your UIViewController subclass:
- (void)loadView {
[super loadView];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
// If you need custom color, use color property
// activityIndicator.color = yourDesirableColor;
[self.view addSubview:activityIndicator];
[activityIndicator startAnimating];
self.activityIndicator = activityIndicator;
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
CGSize viewBounds = self.view.bounds;
self.activityIndicator.center = CGPointMake(CGRectGetMidX(viewBounds), CGRectGetMidY(viewBounds));
}
=============================================================
non-ARC version, iOS < 5.0:
You should override method
-(void)loadView {
[super loadView];
self.activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
[self.view addSubview:self.activityIndicator];
self.activityIndicator.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
[self.activityIndicator startAnimating];
}
Also, add
#property (nonatomic, assign) UIActivityIndicatorView *activityIndicator;
at the header file
and
#synthesize activityIndicator;
to the .m file
I'm not sure why, but I'm having trouble passing a data object (NSManagedObject) to a view controller when that view controller is being instantiated inside another one. When I log the object before it is passed, it has all of its data, but after it gets to the view controller, it is empty. It seems like this should be fairly straight-forward, but for some reason it's just not getting there.
The code which assigns the NSManagedObject to the accepting view controller in the implementation file is: viewController.thisCard = aCard;
Any help is much appreciated. Thanks in advance.
This is the header for the view controller which scrolls:
#interface HandViewController : UIViewController
<UIScrollViewDelegate>
{
IBOutlet UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
BOOL pageControlIsChangingPage;
NSManagedObjectContext *context;
}
#property (nonatomic, retain) UIView *scrollView;
#property (nonatomic, retain) UIPageControl *pageControl;
#property (nonatomic, retain) NSManagedObjectContext *context;
/* for pageControl */
- (IBAction)changePage:(id)sender;
#end
this is the viewDidLoad in the implementation of that object
- (void)viewDidLoad
{
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Game" inManagedObjectContext:[self context]];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *fetchedGames = [self.context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
Game *aGame = [fetchedGames objectAtIndex:0];
CGFloat cx = 0;
for (Card *aCard in aGame.turnUpcoming.hand) {
CardViewController *viewController = [[CardViewController alloc] initWithNibName:#"CardViewController" bundle:nil];
CGRect rect = self.view.frame;
rect.size.height = scrollView.frame.size.height - 50;
rect.size.width = scrollView.frame.size.width - 50;
rect.origin.x = ((scrollView.frame.size.width - rect.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - rect.size.height) / 2);
viewController.view.frame = rect;
viewController.thisCard = aCard;
[scrollView addSubview:viewController.view];
cx += scrollView.frame.size.width;
[viewController release];
}
self.pageControl.numberOfPages = [aGame.turnUpcoming.hand count];
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
UPDATE: Per request, I am adding a bit of code from the view controller
This is the header for CardViewController
#interface CardViewController : UIViewController {
UILabel IBOutlet *cardValue;
UILabel IBOutlet *cardInstruction;
UILabel IBOutlet *cardHint;
UILabel IBOutlet *cardTimer;
UIButton IBOutlet *playCardButton;
Card *thisCard;
}
#property (nonatomic, retain) UILabel IBOutlet *cardValue;
#property (nonatomic, retain) UILabel IBOutlet *cardInstruction;
#property (nonatomic, retain) UILabel IBOutlet *cardHint;
#property (nonatomic, retain) UILabel IBOutlet *cardTimer;
#property (nonatomic, retain) UIButton IBOutlet *playCardButton;
#property (nonatomic, retain) Card *thisCard;
#end
Here is the viewDidLoad from the implementation of CardViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if ([thisCard isObjectValid]) {
cardValue.text = [thisCard.value stringValue];
}
}
UPDATE: new code for card loop in viewDidLoad and new CardView code, per suggestions below
loop in viewDidLoad:
for (Card *aCard in aGame.turnUpcoming.hand) {
CGRect rect = scrollView.frame;
rect.size.height = scrollView.frame.size.height - 50;
rect.size.width = scrollView.frame.size.width - 50;
rect.origin.x = ((scrollView.frame.size.width - rect.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - rect.size.height) / 2);
tempCardView = [[CardView alloc] initWithFrame:rect];
tempCardView.thisCard = aCard;
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CardView" owner:self options:nil];
tempCardView = [nibObjects objectAtIndex:0];
[scrollView addSubview:tempCardView];
cx += scrollView.frame.size.width;
[tempCardView release];
}
header file CardView.h
#interface CardView : UIView {
UILabel IBOutlet *cardValue;
UILabel IBOutlet *cardInstruction;
UILabel IBOutlet *cardHint;
UILabel IBOutlet *cardTimer;
UIButton IBOutlet *playCardButton;
Card *thisCard;
}
#property (nonatomic, retain) UILabel IBOutlet *cardValue;
#property (nonatomic, retain) UILabel IBOutlet *cardInstruction;
#property (nonatomic, retain) UILabel IBOutlet *cardHint;
#property (nonatomic, retain) UILabel IBOutlet *cardTimer;
#property (nonatomic, retain) UIButton IBOutlet *playCardButton;
#property (nonatomic, retain) Card *thisCard;
#end
implementation file CardView.m
#implementation CardView
#synthesize cardHint;
#synthesize cardTimer;
#synthesize cardValue;
#synthesize cardInstruction;
#synthesize playCardButton;
#synthesize thisCard;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
if ([thisCard isObjectValid]) {
cardValue.text = [thisCard.value stringValue];
cardInstruction.text = thisCard.instruction;
cardHint.text = thisCard.hint;
cardTimer.text = [thisCard.time stringValue];
}
}
return self;
}
#end
UPDATED: 6/16 - Added XIB screen shot
CardView.xib
Seems like your CardViewController should actually be a UIView. As Apple says: " A single view controller typically manages the views associated with a single screen’s worth of content, although in iPad applications this may not always be the case."
(After changes to UIView) in your loop, you're creating one tempCard and then loading another. If you've linked tempCardView in IB (see below), then all you need is:
for (Card *aCard in aGame.turnUpcoming.hand) {
CGRect rect;
rect.size.width = scrollView.frame.size.width - 50;
rect.size.height = scrollView.frame.size.height - 50;
rect.origin.x = ((scrollView.frame.size.width - rect.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - rect.size.height) / 2);
[[NSBundle mainBundle] loadNibNamed:#"CardView" owner:self options:nil]; //magically connected to tempCardView.
self.tempCardView.frame = rect;
self.tempCardView.thisCard = aCard;
[scrollView addSubview:tempCardView];
cx += scrollView.frame.size.width;
self.tempCardView = nil;
}
So, you have two XIBs, your main one that loads with your viewController, and one (CardView) that gets loaded once for each card.
Now, inside CardView, you're trying to set up the labels too soon. During initWithFrame (which in the above case is called by loadFromNib), you don't have access yet to thisCard. You'll need a setter for thisCard, which will be called any time a value is assigned to thisCard property:
-(void) setThisCard: (Card *) newCard {
if (thisCard == newCard) return;
[newCard retain];
[thisCard release];
thisCard = newCard;
self.cardValue.text = [thisCard.value stringValue];
self.cardInstruction.text = thisCard.instruction;
self.cardHint.text = thisCard.hint;
self.cardTimer.text = [thisCard.time stringValue];
}
Now in Interface Builder,
Create CardView.xib with a single UIView with, but set FileOwner to your VC, NOT to CardView because that's who's going to load it (and who has the tempCardView property).
Set the view's type to CardView, then hook it to thetempCardView property of FileOwner (aka HandViewController)
Put all your other card parts inside that CardView and hook them up to that CardView's properties.
You should be all set.
So, I am trying to make a shared method in my Brain class which will check the label on a pressed button (buttons of items are in different classes) and then accordingly add a image to a ShoppingList view minding the order of adding (first image added goes to position 0,0, second to position 80,0 etc.).
I have Breakfast class which represents breakfast ingredients and I wanna add a photo of a Tea to another view called ShoppingList.
I wrote a method in Brain that adds an image to a imageView and returns an imageView which is then locally passed to the button pressed.
It builds but when I press the button Tea, application crashes.
Here is my code:
Brain.h
#interface Brain : NSObject {
#private
UIImage *image;
UIImageView *imageView;
}
#property (retain) UIImageView *imageView;
#property (retain) UIImage *image;
- (id)performOperation:(NSString *)operation;
#end
Brain.m
#implementation Brain
#synthesize imageView;
#synthesize image;
- (UIImageView *)performOperation:(NSString *)operation
{
if ([operation isEqual:#"Tea"]) {
image = [UIImage imageNamed:#"Tea_photo.jpg"];
imageView = [[UIImageView alloc]initWithImage:image];
imageView.frame = CGRectMake(0, 0, 80, 80);
return imageView;
//[shoppingList.view addSubview:imageView];
//[imageView release];
}
else return 0;
}
#end
Breakfast.h
#interface Breakfast : UIViewController {
IBOutlet ShoppingList *shoppingList;
Brain *brain;
}
- (IBAction)addItemToShoppingList:(UIButton *)sender;
- (IBAction)goToShoppingList;
- (IBAction)goBack;
#end
Breakfast.m
#implementation Breakfast
- (Brain *)brain
{
if (!brain) brain = [[Brain alloc] init];
return brain;
}
- (IBAction)addItemToShoppingList:(UIButton *)sender
{
NSString *operation = [[sender titleLabel] text];
UIImageView *imageView = [[self brain] performOperation:operation];
[shoppingList.view addSubview:self.brain.imageView];
//UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
//imageView.frame = CGRectMake(0, 0, 80, 80);
//[shoppingList.view addSubview:imageView];
//[imageView release];
}
- (IBAction)goToShoppingList
{
[self presentModalViewController:shoppingList animated:NO];
}
- (IBAction)goBack
{
[self dismissModalViewControllerAnimated:NO];
}
#end
PLEASE HELP, its for my thesis.
IBOutlet ShoppingList *shoppingList;
Why make this IBOutlet? Isn't ShoppingList a class that you created. Not that this solves your crash. For that u need to post the crash log....
And also in you code I can't see any allocation for shoppingList so how can you be able to use it. You need to allocate the object in the class Brain otherwise it doesn't make any sense.
I have not gone through your code. But on the basis of your description I can suggest you to create a protocol