iPhone function to create UILabel fails and crashes - iphone

I have a view with a scrollview. I use code to add labels to the scrollview. Since there's a lot of redundant code, I tried to move the label creation to a separate function that returns a UILabel. Here' that function:
- (UILabel *) f_MakeLabelWithL:(float)MyLeft T:(float)MyTop W:(float)MyWidth H:(float)MyHeight Align:(UITextAlignment)MyAlign
Font:(UIFont *)MyFont TextColor:(UIColor *)MyTextColor BGColor:(UIColor *)MyBGColor {
CGRect rect = CGRectMake(MyLeft, MyTop, MyWidth, MyHeight);
UILabel *label = [[[UILabel alloc] initWithFrame:rect] autorelease];
label.adjustsFontSizeToFitWidth = YES;
label.backgroundColor = MyBGColor;
label.font = MyFont;
label.numberOfLines = 0;
label.textAlignment = MyAlign;
label.textColor = MyTextColor;
return label;
}
I set the text of the label after it is returned. Or so I intended. In fact, a label that is told to have a blue background appears as a solid black rectangle. One with a clear background is entirely clear. Worse than that: the scrollview won't scroll, and attempting to make it do so crashes the app without any explanation in the debugger console.
Yet all this code works inline just fine and dandy.
Anyone know why?
Update: Putting the code inline fixed the display of the labels. But I was also using a function to create images:
- (UIImageView *) f_MakeImageWithL:(float)MyLeft T:(float)MyTop W:(float)MyWidth H:(float)MyHeight File:(NSString *)MyFile {
CGRect rect = CGRectMake(MyLeft, MyTop, MyWidth, MyHeight);
UIImageView *oImageView = [[[UIImageView alloc] initWithFrame:rect] autorelease];
NSString *s = [[Isystant f_DocumentsPath] stringByAppendingPathComponent:MyFile];
UIImage *oImage = [UIImage imageWithContentsOfFile:s];
[oImageView setImage:oImage];
oImageView.backgroundColor = [UIColor redColor];
oImageView.opaque = YES; // explicitly opaque for performance
return oImageView;
}
It was creating the images, but the frozen scroll/crash problem didn't go away until I put this code back inline also.

Looks to me like you are over-releasing the UILabel. You shouldn't have to release the label after adding it to your scrollview if it was never retained anywhere prior to that (and you've autoreleased it in the makeImageWithL method).
That's probably why it is working when you put it inline... because in that scenario, I would bet you are removing the autorelease, right?
-S

Do you retain your returned Label somewhere?

Related

iOS 7 UITextView height resize quirk

Using information I've gathered from multiple answers I found here on stackoverflow, I've been able to correctly size a UITextView's height using:
[bookQuoteTxtView sizeToFit];
[bookQuoteTxtView layoutIfNeeded];
I'm doing this because the UITextView will obviously contain different amounts of text as a result of what the user may have selected on a previous screen.
However, I'm still running into one strange problem.
It seems that when the text that gets passed into the UITextView contains a line-break, it throws the whole height thing off.
Here's the text without any line-breaks:
And here's the same text with a couple of line-breaks thrown in the middle:
As you can see (with the help of the orange & yellow background colors I added to the UITextView & ScrollView that contains it), the UITextView's height didn't resize appropriately and now the text gets cut off - all because of those linebreaks.
The code I'm using to do all this dynamic height-changing on the UITextView is:
// BookQuote TextView:
bookQuoteTxtView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 310, 80)];
bookQuoteTxtView.backgroundColor = [UIColor orangeColor];
bookQuoteTxtView.font = [UIFont fontWithName:#"Arial" size:15];
bookQuoteTxtView.text = [NSString stringWithFormat:#"%#", bookObject.bookQuote];
[bookQuoteTxtView sizeToFit];
[bookQuoteTxtView layoutIfNeeded];
bookQuoteTxtView.editable = NO;
[scroller addSubview:bookQuoteTxtView];
// Now get the HEIGHT of the Book-Quote TextView:
CGRect textViewFrame = bookQuoteTxtView.frame;
CGFloat textViewFrameHeight = bookQuoteTxtView.contentSize.height;
textViewFrame.size.height = textViewFrameHeight;
bookQuoteTxtView.frame = textViewFrame;
So again, this works almost flawlessly for just about every string that gets passed into my UITextView box. Thus, different strings of different lengths all work, the UITextView's height adjusts automatically and everything's cool. Its just the line-breaks that throw everything off.
HAVING SAID THAT...
Its seems that line-breaks generated using "\n" in the string DO work, but line breaks that are embedded/encoded in a string that's coming in and being read from an Sqlite3 database - do NOT.
So you gotta wonder if that's where the problem lies.
Here's the code I use to read my date from the Database:
// Book Quote:
char *bookQuoteChar = (char *)sqlite3_column_text(statement, 4);
NSString *bookQuoteString;
if (bookQuoteChar == NULL) {
bookQuoteString = #"N/A";
}
else {
bookQuoteString = [[NSString alloc] initWithUTF8String:bookQuoteChar];
}
I'm thinking more and more that its the database that's causing the problem, but I'm presenting the entire picture here in its totality to make sure I'm still doing the height-readjustment stuff correctly.
Please let me know if something's jumping out at you or if there are any suggestions for fixes.
I can't really suggest much besides using a technique to set the contentSize of the UITextView.
textView.text = #"text from DB";
CGRect rect = textView.frame;
rect.size.height = textView.contentSize.height;
textView.frame = rect;
and then use any techniques that may be needed to additionally update the frame. Hope you solve the problem!

tableView as subview in a semi-transparent view

I'm developing a little iOS component and I have a problem with a semi-transparent view with subviews. This is my scenario:
- one view with a semi-transparent background using [UIColor colorWithRed:green:blue:alpha]
- a little UITableView, with alpha = 1.0, added as a subview to the semi-transparent view
- some other subviews
Everything works well but the problem raises when the UITableView is scrolled up or down, in fact the area of the semi-transparent view around the UITableView loses its transparency becoming darker than its original background color.
Here's an image to explain the problem:
Look at the space with the two arrows...
Can anyone help me with this problem?
Thank you so much for your attention!
Update:
Some code:
_alertBg = [[UIView alloc] initWithFrame:CGRectZero];
_alertBg.backgroundColor = self.backgroundColor;
_alertBg.frame = CGRectMake((_bgView.frame.size.width - 240) / 2, (_bgView.frame.size.height - 260) / 2, 240, 260);
_alertBg.layer.cornerRadius = 8.0;
_alertBg.layer.borderWidth = 2.0;
_alertBg.layer.borderColor = self.borderColor.CGColor;
_alertBg.layer.shadowColor = [UIColor grayColor].CGColor;
_alertBg.layer.shadowOffset = CGSizeMake(0, 3);
_alertBg.layer.shadowOpacity = 0.8;
_alertBg.layer.masksToBounds = YES;
[_bgView addSubview:_alertBg];
_table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_table.frame = CGRectMake(10, _titleLabel.frame.origin.y + _titleLabel.frame.size.height + 12, _alertBg.frame.size.width - 20, 150);
_table.layer.cornerRadius = 6.0;
_table.layer.masksToBounds = YES;
_table.delegate = self;
_table.dataSource = self;
[_alertBg addSubview:_table];
From the code above, self.backgroundColor is something like [UIColor colorWithRed:0 green:0 blue:1 alpha:0.7]
I put the available code in a test project, and got the same problem as you have. Commenting out _alertBg.layer.shadowOpacity = 0.5; fixes the issue for me. Maybe someone can clarify why is this an issue, I have limited experience with QuartzCore.
EDIT: Okay, inched closer to the real reason. It seems that if you don't have set the _alertBg.layer.shadowPath property all kinds of crazy things happen when you scroll the table (my guess here is that the table scroll calls a redraw of the _alertBg and the shadow redrawing gets called in quick succession far too many times and you get those visual artifacts).
Adding a shadowPath fixes the problem, so the layer code for the _alertBg should be as following:
_alertBg.layer.cornerRadius = 8.0;
_alertBg.layer.borderWidth = 2.0;
_alertBg.layer.borderColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.7].CGColor;
_alertBg.layer.shadowColor = [UIColor grayColor].CGColor;
_alertBg.layer.shadowOffset = CGSizeMake(0, 5);
_alertBg.layer.shadowOpacity = 0.8;
_alertBg.layer.shadowPath = [UIBezierPath bezierPathWithRect:_alertBg.bounds].CGPath;
_alertBg.layer.masksToBounds = YES;
Just fix the shadowPath to your liking and you should be ready to go.
PS: On my Google-quest I found this excellent blog post about shadows, it might be of help.
Maybe match the background colour of tableView with _alertBg?
Its may be problem of dequeueReusableCellWithIdentifier.
just try this..., set dequeueReusableCellWithIdentifier to nil like bellow in cellForRowAtIndexPath method of UITableViewController delegate method
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
Also see my this answer may be you can get some idea from this..
iPhone Hide/Show labels in Uitableview cell

Unable to set transparency in custom cell created programmatically

I have a UITableViewController with custom cells, based in Tweetie's Fast scrolling example and i need transparency.
Until now, i loaded my cells from a nib and all i needed was to set some table's properties to
table.backgroundColor = [UIColor clearColor];
table.opaque = NO;
table.rowHeight = 130.0f;
table.separatorStyle = UITableViewCellSeparatorStyleNone;
in order to make the table transparent. As for the cell, i did:
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellbackground.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellbackground.png"]];
And so i had every cell with a background image but with the rest completely transparent (half of the image is completely transparent). Now, creating the cell programmatically and drawing everything myself, i just can't get to make the cell transparent. The image part looks fine, but everything else is black, not opaque
Figured it out.
The issue was that it wasn't paying attention to my
self.opaque = NO;
because my cell's super class was doing exactly the opposite, setting opaque = YES;. So i changed that and it is working great now.
PS: Thanks for answering and making me pay extra attention to opaque property.
Try this:
cell.backgroundColor =[UIColor clearColor];
You may also need this:
cell.opaque = NO;

UITextview viewWithTag - updating the text doesn't work while I know I have access to it

Hey There, your kind help on a small matter.
I have a UITextview with a tag
// Text view
UITextView *currentPage = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300.0, 194.0)];
currentPage.scrollEnabled = YES;
currentPage.textAlignment = UITextAlignmentLeft;
currentPage.tag = 100;
currentPage.editable = NO;
currentPage.text = #"All is sweet";
[self.view addSubview:currentPage];
[currentPage release];
Some time later, I want to change the above "currentPage" text and replace it's content with some new text.
-(void)loadNewPage{
// works fine, meaning I am "touching" the right object
[self.view viewWithTag:100].alpha = 0.5f;
// So why this one isn't legal syntax ?
//[self.view viewWithTag:100].text = #"A new updated text";
}
The viewWithTag works fine while changing the alpha, Thus I am left wondering about the right syntax to apply for the text update...
-viewWithTag: method returns UIView object, so to set properties specific to UITextview you should cast its type explicitly:
((UITextView*)[self.view viewWithTag:100]).text = #"A new updated text";

How to set background image of a view?

I am a beginner at Obj-C/Cocoa Touch/iPhone OS.
I wish to have a background for my app with different images everytime the the view is called.
Say I have 10 images. I 've used it like this:
//random image generation
NSString* imageName;
int aRandomNumber = arc4random() % 10;
imageName =[NSString stringWithFormat:#"g%d.jpg",aRandomNumber];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:imageName]]];
NSLog(#"aRandomNumber is %d", aRandomNumber);
//random image is generated
Its working fine
Now, say I have text labels on my view and the text isn't displaying correctly due to image colors.
How can I make it a little transparent? (I guess in Interface Builder its called alpha.)
Say my image isn't 320x480. How do I set it to fill the entire view?
How can I do it with UIView/UIImageView?
I found initWithHue:saturation:brightness:alpha: in the documentation but it's not working:
self.view.backgroundColor = [[UIColor alloc] initWithHue:0.0 saturation:1.0 brightness:1.0 alpha:1.0];
Please Help!
A friend suggested........
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:imageName]]];
..........he told it's more efficient because it doesn't save the image in the cache.
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"imageName.png"]];
more info with example project
Besides all of the other responses here, I really don't think that using backgroundColor in this way is the proper way to do things. Personally, I would create a UIImageView and insert it into your view hierarchy. You can either insert it into your top view and push it all the way to the back with sendSubviewToBack: or you can make the UIImageView the parent view.
I wouldn't worry about things like how efficient each implementation is at this point because unless you actually see an issue, it really doesn't matter. Your first priority for now should be writing code that you can understand and can easily be changed. Creating a UIColor to use as your background image isn't the clearest method of doing this.
use this
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Default"]];
simple way :
-(void) viewDidLoad {
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"background.png"]];
[super viewDidLoad];
}
It's a very bad idea to directly display any text on an irregular and ever changing background. No matter what you do, some of the time the text will be hard to read.
The best design would be to have the labels on a constant background with the images changing behind that.
You can set the labels background color from clear to white and set the from alpha to 50.0 you get a nice translucent effect. The only problem is that the label's background is a stark rectangle.
To get a label with a background with rounded corners you can use a button with user interaction disabled but the user might mistake that for a button.
The best method would be to create image of the label background you want and then put that in an imageview and put the label with the default transparent background onto of that.
Plain UIViews do not have an image background. Instead, you should make a UIImageView your main view and then rotate the images though its image property. If you set the UIImageView's mode to "Scale to fit" it will scale any image to fit the bounds of the view.
You want the background color of your main view to be semi-transparent? There's nothing behind it... so nothing will really happen however:
If you want to modify the alpha of any view, use the alpha property:
UIView *someView = [[UIView alloc] init];
...
someView.alpha = 0.8f; //Sets the opacity to 80%
...
Views themselves have the alpha transparency, not just UIColor.
But since your problem is that you can't read text on top of the images... either:
[DESIGN] Reconsider the design/placement of the images. Are they necessary as background images? What about the placement of the labels?
[CODE] It's not exactly the best solution, but what you could do is create a UIView whose frame takes up the entire page and add some alpha transparency to it. This will create an "overlay" of sorts.
UIView *overlay = [[[UIView alloc] init] autorelease];
overlay.frame = self.view.bounds;
overlay.alpha = 0.2f;
[self.view addSubview:overlay];
... Add the rest of the views
You can set multiple background image in every view using custom method as below.
make plist for every theam with background image name and other color
#import <Foundation/Foundation.h>
#interface ThemeManager : NSObject
#property (nonatomic,strong) NSDictionary*styles;
+ (ThemeManager *)sharedManager;
-(void)selectTheme;
#end
#import "ThemeManager.h"
#implementation ThemeManager
#synthesize styles;
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
[sharedManager selectTheme];
return sharedManager;
}
- (id)init
{
if ((self = [super init]))
{
}
return self;
}
-(void)selectTheme{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeName = [defaults objectForKey:#"AppTheme"] ?: #"DefaultTheam";
NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:#"plist"];
self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
}
#end
Can use this via
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:#"backgroundImage"];
[imgViewBackGround setImage:[UIImage imageNamed:imageName]];