10

Im trying to customize UITableViewController dynamically. So i have changed many properties of cell.textLabel. Now i want to copy these properties to detailTextLabel and to one label i have created through code. How it can be done?

    cell.textLabel.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
    cell.textLabel.textColor=[UIColor whiteColor];
    cell.textLabel.font=[UIFont fontWithName:@"HelveticaNeue" size:26];
    cell.textLabel.autoresizingMask=UIViewAutoresizingFlexibleRightMargin;

This is my cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        cell.textLabel.text=[_names objectAtIndex:indexPath.row];
        cell.textLabel.tag=indexPath.row;

        cell.detailTextLabel.text=[_phones objectAtIndex:indexPath.row];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrow.png"] ];
        [imageView setFrame:CGRectMake(380,10,30,50)];
        [cell addSubview:imageView];
        //customize the seperator
        UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1000, 1)];/// change size as you need.
        separatorLineView.backgroundColor = [UIColor grayColor];// you can also put image here
        [cell.contentView addSubview:separatorLineView];
        cell.contentView.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
        cell.textLabel.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
        cell.textLabel.textColor=[UIColor whiteColor];
        cell.textLabel.font=[UIFont fontWithName:@"HelveticaNeue" size:26];
        cell.textLabel.autoresizingMask=UIViewAutoresizingFlexibleRightMargin;
        //here i want to copy the properties
        return cell;
    }
Nikhil Manapure
  • 3,748
  • 2
  • 30
  • 55
Saranjith
  • 11,242
  • 5
  • 69
  • 122

10 Answers10

4

For Swift3

class MyLabel: UILabel {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        backgroundColor = UIColor(red: 0, green: 0.188235, blue: 0.313725, alpha: 1)
        textColor = UIColor.white
        font = UIFont(name: "HelveticaNeue", size: 26)
        autoresizingMask = .flexibleRightMargin
    }
}

Create a subclass of UILabel in this way.

#import "MyLabel.h"

@implementation MyLabel

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    self.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
    self.textColor=[UIColor whiteColor];
    self.font=[UIFont fontWithName:@"HelveticaNeue" size:26];
    self.autoresizingMask=UIViewAutoresizingFlexibleRightMargin;
}

@end

And now create an object of this MyLabel and your properties will be set automatically and also just assign this class to your label through storyboard to the label in your cell.

Subclassing is the best way for implementing reusable code.

Or else you can even create an extension of class or even an class method in some class which accepts the UILabel and sets the properties but this all are not the best practices. Another problem with extensions is the you can only use self but not super. This may create problems in future when you have to extend the properties.

I hope I am clear and helpful.

Nikhil Manapure
  • 3,748
  • 2
  • 30
  • 55
2

You can use this method to make all the labels of UITabelViewCell to same property

Here just loop through the subViews and check whether the subview is of UILabel, If it is of UILabel then set the property you want.

My Code :

- (void)formatTheLabelForCell:(UITableViewCell *)cell
{
    for (UIView *view in cell.contentView.subviews) {
        if ([view isKindOfClass:[UILabel class]]) {
            UILabel *lbl = (UILabel *)view;

            lbl.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
            lbl.textColor=[UIColor whiteColor];
            lbl.font=[UIFont fontWithName:@"HelveticaNeue" size:26];
            lbl.autoresizingMask=UIViewAutoresizingFlexibleRightMargin;
        }
    }
}
Janmenjaya
  • 4,149
  • 1
  • 23
  • 43
  • Its working fine. I want to know is there any code which does the copying and pasting of tools in XCode editor dynamically. – Saranjith Sep 28 '16 at 10:09
  • I have called your 'formatTheLabelForCell' from 'cellForRowAtIndexPath' but I m having many raws in 'ViewController' around 100 so its taking longer time. Looping through views everytime in creation of cell – Saranjith Sep 28 '16 at 10:17
  • It is not recommended to use this much cell to load simultaneously. Even if you did not use load more, are you showing 100 cells in the screen in a single time ?? – Janmenjaya Sep 28 '16 at 10:23
  • Ya I have. That was a client need. – Saranjith Sep 28 '16 at 12:20
2

Instead of configuring cell in cellForRowAtIndexPath, it's better if you use custom cell. Add imageView & separatorLineView in your Storyboard/ Nib itself. This way all cells are generated with these default properties. Also if you need to configure something through code, you can code it in your CustomCell.m file like this:

 class CustomCell: UITableViewCell {
    override func awakeFromNib() {
    super.awakeFromNib()
    self.textLabel.backgroundColor = UIColor.redColor
    //do other configurations
    }

Edit: Downloading images from web may be the reason for taking long time loading cells. Try downloading images asynchronously. You can also use this library: SDWebImage

Note: I know you want it in Objective C, above code in Swift is just for illustration.

Arpit Dongre
  • 1,683
  • 19
  • 30
2

As for swift, you can do this, it will copy all the attributes you applied to textLabel to detailTextLabel.

 cell.detailTextLabel.attributedText = cell.textLabel.attributedText
Samip Shah
  • 854
  • 7
  • 11
2

First of all I don't think that there is a function to copy specific properties of a any UIKit component in iOS SDK. Therefore for you will have to write a custom function for this. Additionally there are some issues with your "cellForRowAtIndexPath" as pointed out by others in comments.

There are different solutions to this.

Solution 1: Write a function in your view controller which take two labels as parameters and copy your desired values.

-(void)copyPropertiesFrom:(UILabel*)label1 toLabel:(UILabel*)label2{
    label2.backgroundColor  = label1.backgroundColor;
    label2.textColor        = label1.textColor;
    label2.font             = label1.font;
    label2.autoresizingMask = label1.autoresizingMask;
}

In cellForRowAtIndexPath where you want to copy do this

[self copyPropertiesFrom:cell.titleLabel toLabel:cell.detailTextLabel];

Solution 2(Recommended): This is best in my little experience because you can reuse it in other view controllers. There might be a better approach than this.

Create a category of UILabel. Check this link How do I create a category in Xcode 6 or higher? and also this https://code.tutsplus.com/tutorials/objective-c-categories--mobile-10648

Your function within category will look like this.

-(void)formatLabelToMyStyle{
    self.backgroundColor    = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
    self.textColor          = [UIColor whiteColor];
    self.font               = [UIFont fontWithName:@"HelveticaNeue" size:26];
    self.autoresizingMask   = UIViewAutoresizingFlexibleRightMargin;
}

You will include header file of category and call this function in your cellForRowAtIndexPath like this

[cell.titleLabel formatLabelToMyStyle];
[cell.detailTextLabel formatLabelToMyStyle];
[cell.customTextLabel formatLabelToMyStyle];

And as for your cellForRowAtIndexPath, larme mentioned in comments "Don't add subview like that in cells because cells are reused" This will keep adding views to your cell hence causing memory issues, Specially when you have large number of cell which in your case is true.

Community
  • 1
  • 1
ibnetariq
  • 718
  • 1
  • 4
  • 20
2

You could use a Category for UILabel or use a subclass of UILabel that should share the same styling.

A Category for the UILabel could look like:

// UILabel+CustomStyle.h
#import <UIKit/UIKit.h>

@interface UILabel (CustomStyle)
-(void) applyCustomStyle;
@end

.m file:

// UILabel+CustomStyle.m
#import "UILabel+CustomStyle.h"

@implementation UILabel (CustomStyle)

-(void) applyCustomStyle {
    self.backgroundColor = [UIColor colorWithRed: 0 green: 0.188235 blue: 0.313725 alpha: 1];
    self.textColor = [UIColor whiteColor];
    self.font = [UIFont fontWithName: @"HelveticaNeue" size: 26];
    self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
}

@end

Then you can apply the same styling by simply calling:

#import "UILabel+CustomStyle.h"
[label applyCustomStyle];
d.felber
  • 5,288
  • 1
  • 21
  • 36
2

If you want to use same label configuration to many places in project. Just subclass as @NikhilManapure said.

OR

If you want to apply same properties to TableViewCell textLabel and detailTextLabel. You should subclass TableViewCell and override Label properties in drawrect method.

Objective-C

        #import <UIKit/UIKit.h>

        @interface PropertiesCell : UITableViewCell

        @end

        #import "PropertiesCell.h"

        @implementation PropertiesCell

        - (void)awakeFromNib {
            [super awakeFromNib];
            // Initialization code
        }

        - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
            [super setSelected:selected animated:animated];

            // Configure the view for the selected state
        }

        - (void)drawRect:(CGRect)rect {
            [super drawRect:rect];
            [self cellLabelConfigure:self.textLabel];
            [self cellLabelConfigure:self.detailTextLabel];
        }

        - (void)cellLabelConfigure:(UILabel*) contentLabel {
            contentLabel.backgroundColor = [UIColor colorWithRed:0 green:0.188235 blue:0.313725 alpha:1];
            contentLabel.textColor=[UIColor whiteColor];
            contentLabel.font=[UIFont fontWithName:@"HelveticaNeue" size:26];
            contentLabel.autoresizingMask=UIViewAutoresizingFlexibleRightMargin;
        }

        @end

Swift

 class PropertiesCell: UITableViewCell {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        cellLabelsConfigure(contentLabel: self.textLabel)
        cellLabelsConfigure(contentLabel: self.detailTextLabel)
    }

    func cellLabelsConfigure(contentLabel: UILabel?) {
        contentLabel?.backgroundColor = UIColor(red: 0.0, green: 0.188, blue: 0.313, alpha: 1.0)
        contentLabel?.textColor = UIColor.white
        contentLabel?.font = UIFont(name: "HelveticaNeue", size: 26.0)
        contentLabel?.autoresizingMask = UIViewAutoresizing.flexibleRightMargin
    }
}

In storyboard change cell class name to PropertiesCell

enter image description here

abhi
  • 563
  • 6
  • 9
1

Create an extension class and use this copy method to pass all the properties you want to the new label.

@implementation UILabel (Copy)

- (UILabel *)copyProperties {
    UILabel *label = [UILabel new];
    [self copyPropertiesWithLabel:label];
    return label;
}

- (void)copyPropertiesWithLabel:(UILabel *)label {
    label.backgroundColor = self.backgroundColor;
    label.textColor = self.textColor;
    label.font = self.font;
    label.autoresizingMask = self.autoresizingMask;
    // Add more properties
}

@end

Usage:

// cell.textLabel has now all the properties
[theLabelToBeCopied copyPropertiesWithLabel:cell.textLabel];
1

Swift3 version:

extension UILabel {

    func copyProperties() -> UILabel {
        var label = UILabel()
        self.copyProperties(with: label)
        return label
    }

    func copyProperties(with label: UILabel) {
        label.backgroundColor = self.backgroundColor
        label.textColor = self.textColor
        label.font = self.font
        label.autoresizingMask = self.autoresizingMask
        // Add more properties
    }
}

Usage:

theLabelToBeCopied.copyProperties(with: cell.textLabel)
0

you can do this for swift.it will copy for all attributes (textLabel to detailTextLabel).i think @Nikhil Manapure given exact answer.

cell.detailTextLabel.attributedText = cell.textLabel.attributedText
heart hacker
  • 431
  • 2
  • 8
  • 22