iOS7 introduced a wonderful "letterpress" text effect that applied via AttributedText to UILabel texts. I need to have that effect in cells of simple table.
Unfortunately being rendered in standard way it caused significant scrolling lags in compare to "textLabel.text" assignments.
Seems attributed text render is very CPU expensive, but iOS embedded apps like Notes scroll without lags. Is it possible to improve render performance?
Below is code sample:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = (MyCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[MyCell alloc] init];
}
NSDictionary *attrs = #{NSTextEffectAttributeName : NSTextEffectLetterpressStyle};
NSString *text = [self textWithCell:indexPath];
//next line causes lags
textLabel.attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:attrs];
//this works fine
//cell.textLabel.text = text;
}
Related
Why isn’t my table view not working smoothly? I use SDWebImage to set the image from a URL. I'm trying to draw 3 images in each row of the table view.
It works fine when arrList is small, but when I increase arrList, it becomes slower and slower (look like a little vibration when I scroll the table view).
This is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
CustomCellTable *cell = (CustomCellTable*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray * nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCellTable" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell setBackgroundColor:brgColor];
// item 1
if ((indexPath.row*3) > arrList.count-1) return cell;
vod *Item = [arrList objectAtIndex:(indexPath.row*3)];
[cell.image1 setHidden:NO];
[cell.image1 setImageWithURL:[NSURL URLWithString:Item.imageURl] placeholderImage:[UIImage imageNamed:#"poster_default.png"]];
[cell makeRating:[Item.rating floatValue] positionOf:14];
// item 2
if ((indexPath.row*3 +1) > arrList.count-1) return cell;
Item = [arrList objectAtIndex:(indexPath.row*3+1)];
[cell.image2 setHidden:NO];
[cell.image2 setImageWithURL:[NSURL URLWithString:Item.imageURl] placeholderImage:[UIImage imageNamed:#"poster_default.png"]];
[cell makeRating:[Item.rating floatValue] positionOf:118];
// item 3
if ((indexPath.row*3 +2) > arrList.count-1) return cell;
Item = [arrList objectAtIndex:(indexPath.row*3+2)];
[cell.image3 setHidden:NO];
[cell.image3 setImageWithURL:[NSURL URLWithString:Item.imageURl] placeholderImage:[UIImage imageNamed:#"poster_default.png"]];
[cell makeRating:[Item.rating floatValue] positionOf:225];
return cell;
}
Look into down sampling the images so you're not storing/loading the large versions of the images while scrolling.
https://github.com/toptierlabs/ImageCacheResize
This library combines SDWebImage with UIImage+Resize. Using it instead of just SDWebImage might help. Specifically use the following method to load the images:
- (void)setImageWithURL:(NSURL *)url andResize:(CGSize)size withContentMode:(UIViewContentMode)mode;
I've spent some time writing an xcode application today. I'm using a UITableView with a seperate xib for the table view cell. All is working well besides one quirky thing. In my code I set my image on the table cell xib from an array. When i run the app I've found out that the image does not appear on the table cell until I click on the table cell. And when I click on a different cell, the image on my previously selected cell disappears.
Funny thing is that I set my label on the table cell xib exactly the same way however I don't get the issue with the label.
Here is my code. I would greatly appreciate some help.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tbHealthCheck dequeueReusableCellWithIdentifier:#"CONTENT"]; //all the cells in this table are named content (identifier for all cells in table)
if (cell == nil){
[[NSBundle mainBundle] loadNibNamed:#"FirstViewTableCell" owner:self options:nil];
cell = tcHealthCheck;
tcHealthCheck = nil;
}
UILabel *l1 = (UILabel *) [cell viewWithTag:0];
[l1 setText:[healthCheckCategory objectAtIndex:indexPath.row]];
l1.font = [UIFont fontWithName:#"arial" size:14];
[l1 setTextColor:[UIColor blackColor]];
UIImageView *img1 = (UIImageView *) [cell viewWithTag:1];
NSString *status = [healthCheckStatus objectAtIndex:indexPath.row];
if ([status isEqualToString:#"RED"])
{
img1.image = [UIImage imageNamed:#"red-light-badge.png"];
}
else if ([status isEqualToString:#"YELLOW"])
{
img1.image = [UIImage imageNamed:#"yellow-light-badge.png"];
}
else if ([status isEqualToString:#"GREEN"])
{
img1.image = [UIImage imageNamed:#"green-light-badge.png"];
}
return cell;
}
I am having this issue where my custom table view cell isn't indenting its content when being shown in a grouped style.
static NSString *CellIdentifier = #"GameListCell";
GameViewCell *cell = (GameViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"GameViewCell" owner:self options:nil];
for (UIView *view in views)
{
if ([view isKindOfClass:[GameViewCell class]])
{
cell = (GameViewCell *)view;
}
}
}
Board *game = (Board *)[boardArray objectAtIndex:indexPath.row];
cell.opponentName.text = [NSString stringWithFormat:#"Game vs %#",game.opponentName];
cell.gameDescription.text = [NSString stringWithFormat:#"Last Move: %#",game.opponentName];
return cell;
Does anyone have any clue what might be going on?
I can't post an image yet, but basically the content is too far left and is outside of the rounded rectangle of the cell.
I'm thinking it might have something to do with the Horizontal Space Constraint in the XIB file for the table view cell.. It has a value of "Constant" and "20". But how do I make the stuff show up in the Content View of the cell?
It looks fine in the "Plain" style, but doesn't indent for grouped style.
Thanks!
I have a UITableView with seven rows each containing text and a .png image. When I add the code to set the image for each row and run the app in the simulator I experience a long loading time.
I suspect that the cause of the performance issue is the fact that my image sizes are too big and I am in the process of scaling my images to the appropriate pixel dimensions. However, I wanted to ensure there is nothing that I could be doing differently in my code to further optimize performance. Is there anything I should be doing differently in my code?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *c = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!c)
{
c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
//adds text to table view
[[c textLabel] setText:[categoryNames objectAtIndex:[indexPath row]]];
[[c textLabel] setTextColor:[UIColor whiteColor]];
//add pictures to table view
NSString *path = [[NSBundle mainBundle] pathForResource:[categoryURLs objectAtIndex:[indexPath row]] ofType:#"png"];
[[c imageView] setImage:[UIImage imageWithContentsOfFile:path]];
return c;
}
Problem solved by resizing images to 44x44 px (standard UITableViewCell height) and 88x88 for the #2x retina images.
I have a local SQLite Database and need to return a large number of records. It takes a several seconds to load so I want to add an activity indicator. The activity indicator seems to be running as it should but the problem is the pool isn't allowing the arrays to return any value see below.
- (void)viewDidLoad
{
[super viewDidLoad];
activityIndicator = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
activityIndicator.frame = CGRectMake(0.0, 0.0, 48.0, 48.0);
activityIndicator.center = self.view.center;
[self.view addSubview:activityIndicator];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[activityIndicator startAnimating];
[self performSelectorInBackground:#selector(loadData) withObject:nil];
}
//What I need to load from SQLITE
-(void)loadData {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Path to the database
//CODED HERE FOR DATABASE TO OPEN AND QUERY HERE TO BUILD ARRAYS
NSString *firstField = [NSString stringWithUTF8String:cFirst];
NSString *secondField = [NSString stringWithUTF8String:cSecond];
NSString *thirdField = [NSString stringWithUTF8String:cThird];
[FirstArray addObject:firstField];
[SecondArray addObject:secondField];
[ThirdArray addObject:thirdField];
//Checking to see if records are being added to the arrays
NSString *recordAdded = [NSString stringWithFormat:#"%# - %# - %#", firstField, secondField, thirdField];
NSLog(#"Song: %#", recordAdded);
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[activityIndicator stopAnimating];
[pool release];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
NSString *firstValue = [firstArray objectAtIndex:indexPath.row];
NSString *secondValue = [secondArray objectAtIndex:indexPath.row];
NSString *thirdValue = [thirdArray objectAtIndex:indexPath.row];
NSString *details = [NSString stringWithFormat:#"%# - %#", secondValue, thirdValue];
cell.textLabel.text = cellValue;
cell.detailTextLabel.text = details ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
When I'm looking at the debugger I see that the arrays are being built as the activity indicator is going. The problem is that I think the pool release is releasing my arrays too.
The code returns the query in the table view fine when I don't add the Pool and activity indicator.
Can anyone help to point me in the right direction to not release the arrays if that's what is happening here? Any kind of help would be much appreciated. :-)
---Also---
After looking around more I found that I have to pass the arrays back to the main thread. This is what I gather from searching online.
[self performSelectorOnMainThread:#selector(done:) withObject:cellData waitUntilDone:NO];
How would I go about loading the table with these arrays?
Not sure about your pool releasing the array, your code seems pretty direct. You may want to check whether you are really getting any data from your database.
However, I notice that you stop animating the activity indicator in the background thread. UI activity should be done in the main thread. I just did this coding last night and solved my problem using this thread. Put your stop animating code in the selector specified by performSelectorOnMainThread.
The strings are fine because they are being added to the array.
It looks like your array is being released, but you don't show the code for it.
How are you creating the array itself? If it is autoreleased, it will be deallocated when you drain the pool. You should "retain" it instead of "auotrelease"ing it.
Try to add [tableview reloadData] at the end of the -(void)loadData method