I used the code to try set the label text but its not working. I though maybe I forgot to connect the outlet with the label, or i connected the wrong outlet but they were ok once I checked them. Made sure the xib was saved.
.m
#synthesize nameLabel;
#synthesize infoLabel;
-(void) updateUI
{
nameLabel.text = #"test1";
infoLabel.text = #"test2";
}
.h
UILabel * nameLabel;
UILabel * infoLabel;
#property(nonatomic, retain) IBOutlet UILabel *nameLabel;
#property(nonatomic, retain) IBOutlet UILabel *infoLabel;
Thats pretty much all the code used in the veiw controller related to these labels. Is there something i am missing that might explain this strangeness?
The default text i have in the labels 'name' & 'info' is what is showing.
This is the code that gets called prior to updateUI being called
browseDeckViewController.m
-(void) viewDidLoad
{
cardOnTopOfDeck = 0;
cardSecondFromTopOfDeck=1;
deck = [[Deck alloc] init];
[deck loadDeckData];
Card *mySecondCard = [[Card alloc] init];
mySecondCard = [deck.deckArray objectAtIndex:cardSecondFromTopOfDeck];
secondCard = [[CardViewController alloc] initWithNibName:#"CardViewController"
bundle:[NSBundle mainBundle] numberOfStats:kNumStats];
[secondCard setCard:mySecondCard];
CGRect frame = secondCard.view.frame;
frame.origin.x = (320-frame.size.width)/2;
frame.origin.y = 10;
secondCard.view.frame = frame;
[self.view addSubview:secondCard.view];
topCard = [[CardViewController alloc] initWithNibName:#"CardViewController"
bundle:[NSBundle mainBundle] numberOfStats:kNumStats];
Card *myTopCard = [[Card alloc] init];
myTopCard = [deck.deckArray objectAtIndex:cardOnTopOfDeck];
[topCard setCard:myTopCard];
frame = topCard.view.frame;
frame.origin.x = (320-frame.size.width)/2;
frame.origin.y = 10;
topCard.view.frame = frame;
[self.view addSubview:topCard.view];
}
CardViewController.m
-(void) setCard:(Card *)newCard
{
[card release];
card = [newCard retain];
[self updateUI];
}
-(void) updateUI
{
NSLog(#"updateUI");
nameLabel.text = #"test1";
infoLabel.text = #"test2";
}
Your CardViewController is created and then you immediately try to set the text of a UILabel in that controller's view. The problem is, the view isn't loaded yet. At the time updateUI is called, viewDidLoad: has not yet been called for the CardViewController, which means nameLabel and infoLabel are nil.
You have to force the CardViewController's view to load from the NIB before trying to access any of the outlets. a simple [self view]; would suffice. For example:
-(void) updateUI {
NSLog(#"nameLabel's value: %#",nameLabel); //nil here
[self view];
NSLog(#"nameLabel's value after loading view: %#",nameLabel); //Now it's loaded
nameLabel.text = #"test1";
infoLabel.text = #"test2";
}
EDIT:
Another solution would be to move the call to updateUI to after addSubview:
myTopCard = [deck.deckArray objectAtIndex:cardOnTopOfDeck];
[self.view addSubview:topCard.view];
[topCard setCard:myTopCard];
frame = topCard.view.frame;
frame.origin.x = (320-frame.size.width)/2;
frame.origin.y = 10;
topCard.view.frame = frame;
This code is incorrect:
nameLabel.text = "test1";
infoLabel.text = "test2";
You are assigning char* pointers to an NSString* variable; you need to prefix the string with the # symbol.
Assuming that the updateUI method is called, nameLabel and infoLabel both exist when it is called, this should work:
nameLabel.text = #"test1";
infoLabel.text = #"test2";
Related
I have a UIView that contains drop shadows and corners which I am loading four of in my UIViewController and I am seeing a performance hit when the screen loads. Since I am using the same white background with shadows and corner radii I figured I would store the UIView in NSCache.
When I run the app there is a large gap where the first UIView should be, however, it is not showing up. What does show up is the last view in my list of views. If I comment out the last one and run it again, the third one shows up. It seems like I am having an issue with the pointer in memory but not sure. Perhaps I am using NSCache incorrectly?
(Note: The first view shown is not using the NSCache)
Here is how I am using the NSCache:
.h file
#interface LunchDetailViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) NSCache *entreeViewsCache;
#end
.m file
#synthesize scrollView;
#synthesize entreeViewsCache;
- (void)viewDidLoad
{
[super viewDidLoad];
self.entreeViewsCache = [[NSCache alloc] init];
UIView *entreeView = [[UIView alloc] init];
entreeView.backgroundColor = [UIColor whiteColor];
entreeView.layer.masksToBounds = NO;
entreeView.layer.cornerRadius = 3.0;
entreeView.layer.shadowOffset = CGSizeMake(1.1, 2.1);
entreeView.layer.shadowOpacity = 0.2;
[self.entreeViewsCache setObject:entreeView forKey:#"EntreeView"];
}
- (void) configureScrollView
{
// This line of code allows the scroll view to be 'scrollable'.
self.scrollView.contentSize = CGSizeMake(320, 620);
UIView *elementaryRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
elementaryRoundedCornerView.frame = CGRectMake(15,15,290,180);
UIView *middleRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
middleRoundedCornerView.frame = CGRectMake(15,210,290,180);
UIView *highRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
highRoundedCornerView.frame = CGRectMake(15,404,290,180);
NSMutableArray *entreeItems = [[NSMutableArray alloc] initWithObjects:#"Pancakes w/ Sausage Patties", #"Corn Dog", #"Grilled Cheese Sandwhich", #"Chicken Tender Wraps", nil];
UIView *elementaryLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[elementaryLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 5, 215, 160) schoolType:#"Elementary"]];
[elementaryRoundedCornerView addSubview:elementaryLunchMenuDetails];
UIView *middleLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[middleLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"Middle"]];
[middleRoundedCornerView addSubview:middleLunchMenuDetails];
UIView *highLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10,10, 240, 160)];
[highLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"High"]];
[highRoundedCornerView addSubview:highLunchMenuDetails];
[self.scrollView addSubview:elementaryRoundedCornerView];
[self.scrollView addSubview:middleRoundedCornerView];
[self.scrollView addSubview:highRoundedCornerView];
}
Wow. That's clever. But not correct.
Instead of using NSCache to duplicate a view, you probably want to create a UIView subclass that formats the view the way you want. Then just throw a bunch of those views on your scrollview.
ABCView.m
#implementation ABCDayView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 3.0;
self.layer.shadowOffset = CGSizeMake(1.1f, 2.1f);
self.layer.shadowOpacity = 0.2f;
}
return self;
}
- (void)setItems:(NSArray *)items
{
if ([_items isEqualToArray:items] == NO) {
_items = items;
[self createItemViews];
[self setNeedsLayout];
}
}
// You'll also need to add -createItemViews and -setNeedsLayout methods.
.m file
- (void)configureScrollView
{
NSMutableArray *entreeItems = #[#"Pancakes w/Sausage Patties",
#"Corn Dog",
#"Grilled Cheese Sandwhich",
#"Chicken Tender Wraps"];
CGRect frame = CGRectMake(15,15,290,180);
ABCDayView *elementaryView = [[ABCDayView alloc] initWithFrame:frame];
elementaryView.items = entreeItems;
CGFloat y = CGRectGetMaxY(elementaryView.frame) + 10.0f;
frame = CGRectMake(15, y, 290, 180);
ABCDayView *middleView = [[ABCDayView alloc] initWithFrame:frame];
middleView.items = entreeItems;
...
CGFloat length = // Use CGRectGetMaxY on the last frame to get the length.
self.scrollView.contentSize = CGSizeMake(320, length);
}
That's by no means perfect code. But hopefully it will give you an idea of a better way to implement this.
So I have class called CSImageViews (subclass of uiview), that is essentially a row of UIImageViews enclosed in a single subclassed UIView.
I've added a custom init method like so (node/yaml contains uiimage name data):
- (id)initWithFrame:(CGRect)frame withNode:(NSDictionary *)node
{
self = [super initWithFrame:frame];
if (self) {
_node = node;
_imageViewYAML = [node objectForKey:#"items"];
_imageViews = [self getImageViewsForItems:_imageViewYAML];
}
return self;
}
And my getImageViewsforItems is like so (adds them all to subview):
-(NSArray *)getImageViewsForItems:(NSArray *)items
{
NSMutableArray *ivs = [NSMutableArray arrayWithCapacity:[items count]];
for (int i = 0; i < [items count]; i++) {
NSDictionary *item = [items objectAtIndex:i];
NSString *type = [item objectForKey:#"type"];
NSString *name = [item objectForKey:#"name"];
UIImage *image = [UIImage imageNamed:name];
UIImageView *iv = [[UIImageView alloc] init];
iv.image = image;
iv.tag = i;
[ivs addObject:iv];
[self addSubview:iv];
}
return ivs;
}
Now when I add this custom view to my main view like this nothing happens:
CSImageViews *imageViews = [[CSImageViews alloc] initWithFrame:frame withNode:node];
[view addSubview:imageViews];
But if I add this 'csimageviews' container into a new uiview first it appears:
CSImageViews *imageViews = [[CSImageViews alloc] initWithFrame:frame withNode:node];
UIView *v = [[UIView alloc] initWithFrame:frame];
[v addSubview:imageViews];
[view addSubview:v];
thoughts?
Stupid error by me. In this particular subclassed UIView I have a method that was called every time its parent view controller was shown. This method actually removed all subviews from the view... so I wasn't able to see the uiimageviews when I rendered it in the initial view... doh.
I try to add Image into my view that in UIScrollView
here is my .h
#interface NormalDetail : UIViewController <UIScrollViewDelegate> {
IBOutlet UIImageView *lineImg;
}
#property (nonatomic, retain) UIImageView *lineImg;
#end
and here is my .m
- (void)viewDidLoad
{
[super viewDidLoad];
//Set ScrollView
scrollView.contentSize = CGSizeMake(320.0f, 1800.0f);
//End Set ScrollView
[self setupTextView];
}
- (void) setupTextView
{
textDescription.scrollEnabled = NO;
NSString *foo = #"Hello Test";
textDescription.text = foo;
/*Here is something for dynamic textview*/
CGRect frame;
frame = textDescription.frame;
frame.size.height = [textDescription contentSize].height;
textDescription.frame = frame;
/**/
int linePosition = frame.size.height+20;
lineImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"line.png"]];
CGRect line2Frame = CGRectMake(-8, 600, 328, 10);
lineImg.frame = line2Frame;
}
What's wrong with my code , My pic didn't appear. help me please ;(
You will needed to the UIImageView to the scorllView.
- (void) setupTextView
{
textDescription.scrollEnabled = NO;
NSString *foo = #"Hello Test";
textDescription.text = foo;
/*Here is something for dynamic textview*/
CGRect frame;
frame = textDescription.frame;
frame.size.height = [textDescription contentSize].height;
textDescription.frame = frame;
/**/
int linePosition = frame.size.height+20;
lineImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"line.png"]];
CGRect line2Frame = CGRectMake(-8, 600, 328, 10);
lineImg.frame = line2Frame;
//Add the image view as a subview to yout scrollview.
[scrollView addSubView:lineImg];
}
I have problem with can't set new text in UITextView .I already link up the IBOutlet to textView in interface builder. Here is my code
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Detail";
[self setupTextView];
}
- (void) setupTextView
{
self.textDescription = [[[UITextView alloc] init] autorelease];
NSString *foo = #"blah blah blah";
textDescription.text = foo; //I try this and it didn't work
//here didn't work too.
//textDescription.text = [textDescription.text stringByAppendingString:foo];
/*Here is something for dynamic textview*/
CGRect frame;
frame = textDescription.frame;
frame.size.height = [textDescription contentSize].height;
textDescription.frame = frame;
/**/
}
Thank you for anu help :)
self.textDescription = [[[UITextView alloc] init] autorelease];
I think this is the problem. If textDescription is an IBOutlet you don't need to allocate it. Just remove this allocation.
I need to create a a bunch a views on the fly. I was wondering what would be the best way to go about doing this as ill need to define coordinates, tag, colours of each view.
Would i need to create a multidimensional array and if so how can i do this?
CGRect viewRect1 = { 80.0, 200.0, 160.0, 100.0 };
UIview *myview1 = [[UIview alloc] initWithFrame:viewRect1];
[myview1 setBackgroundColor:[UIColor darkGrayColor]];
You need to define a structure to hold the data which is needed to create your UIView.
#interface MyViewDataHolder :NSObject
{
CGRect mViewRect;
UIColor* mDarkGrayColor;
NSInterger mTag;
}
#end
Then create an object of above class AND assign the values in member then add that in your NSArray...
EDITED:
In MyViewDataHolder.h class
#interface MyViewDataHolder :NSObject
{
CGRect mViewRect;
UIColor* mDarkGrayColor;
NSInteger mTag;
}
#property (nonatomic,assign) CGRect mViewRect;
#property (nonatomic,retain) UIColor* mDarkGrayColor;
#property (nonatomic,assign) NSInteger mTag;
#end
In MyViewDataHolder.mm class
#import "MyViewDataHolder.h"
#implementation MyViewDataHolder
#synthesize mViewRect,mDarkGrayColor,mTag;
-(void) dealloc
{
[mDarkGrayColor release]
mDarkGrayColor = nil;
}
Now How to use it ....
Create objects of MyViewDataHolder like below ...
MyViewDataHolder* myObj1 = [[MyViewDataHolder alloc] init];
myObj1.mViewRect = CGRectMake(x,y,width,height);
myObj1.tag = 1;
myObj1.mDarkGrayColor = [UIColor redColor];
Create as much as you need
Then Create an NSMutableArray and add each objects of MyViewDataHolder into NSMutableArray.
NSMutableArray* myArray = [[NSMutableArray alloc] init];
[myArray addObject:myObj1];
[myArray addObject:myObj2];
[myArray addObject:myObj3];
and So on ....
When you need the stored info you could use as below ...
for(int index =0; index < [myArray count]; index++)
{
MyViewDataHolder* myObj = (MyViewDataHolder*)[myArray objectAtIndex:index];
myView = [[UIView alloc] initWithFrame:myObj.mViewRect];
//incriment x and y to refelect where you want your next view to be suituated
myView.tag = myObj.mTag;
myView.backgroundColor = myObj.mDarkGrayColor;
[self.view addSubview:myView];
[myView release];
}
The code reflect the approach , Although I didn't compile the code So use it as reference
Thanks ,
You dont really need to store your views in an array unless its just for pure convenience.
You can create a variable amount views using a for loop:
UIView *myView;
int x=0, y=0;
int viewWidth = 50, viewHeight = 50;
for(int i=0; i<numberOFView; i++){
myView = [[UIView alloc] initWithFrame:CGRectMake(x,y,viewWidth,viewHeight)];
//incriment x and y to refelect where you want your next view to be suituated
myView.tag = i+1;
[self.view addSubview:myView];
[myView release];
}
Then to access each view in turn and carry out some work you can do the following:
for (UIView *view in self.view.subviews) {
switch (view.tag) {
case 1:
//do something to the view
break;
case 2:
//do something to the view
break;
case 3:
//do something to the view
break;
//and so on...
default:
break;
}
}