layoutsubviews бесконечный l oop в подклассе UIButton - PullRequest
0 голосов
/ 11 февраля 2020

Приложение, над которым я работаю, имеет настроенный класс UIButton, который должен создавать закругленную кнопку размера в зависимости от его заголовка.

С момента обновления до iOS 13 что-то происходит странное:

при первом появлении вида, содержащего эти кнопки, все работает хорошо. Затем я переключаюсь на другой контроллер представления, затем go возвращаюсь к представлению с помощью кнопок, и здесь я получаю бесконечное значение l oop для метода -layoutsubviews.

Это настраиваемый класс:

#import "RoundedButton.h"

@interface RoundedButton()
@property (nonatomic, retain) NSString *text;
@end

@implementation RoundedButton

-(void)awakeFromNib{
    [super awakeFromNib];
    _text = self.currentTitle;
    [super setTitle:@"" forState:UIControlStateNormal];
}

-(void)layoutSubviews{
    [super layoutSubviews];
    NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    style.alignment = NSTextAlignmentCenter;

    NSDictionary <NSString *, id>*attr = @{  NSFontAttributeName:self.titleLabel.font, NSParagraphStyleAttributeName:style };
    CGRect r = self.bounds;
    r.size = [_text sizeWithAttributes:attr];
    r.size.width += 20;
    r.size.height += 20;

    r.size.width = MAX( r.size.width, 200 );
    r.size.height = MAX( r.size.height, 40 );

    [self setBounds:r];
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    if ( ![self.backgroundColor isEqual:[UIColor clearColor]] ){
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:_cornerRounded];

        CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
        [bezierPath fill];


        //CGContextSetBlendMode(context, kCGBlendModeCopy);
        //CGContextFillRect(context, self.bounds);
        CGContextSetBlendMode(context, kCGBlendModeClear);

        NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
        style.alignment = NSTextAlignmentCenter;

        NSDictionary <NSString *, id>*attr = @{  NSFontAttributeName:self.titleLabel.font, NSParagraphStyleAttributeName:style };

        CGSize szText = [_text sizeWithAttributes:attr];

        CGRect r = self.bounds;
        r.origin.y += (r.size.height - szText.height)/2;

        [_text drawInRect:r withAttributes:attr];
    }
}

-(void)setEnabled:(BOOL)enabled{
    [super setEnabled:enabled];
    if ( !enabled ){
        self.alpha = 0.8;
    }
    else{
        self.alpha = 1.0;
    }
}

-(void)setTitle:(NSString *)title forState:(UIControlState)state{
    _text = title;
    [self setNeedsDisplay];
}


-(void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state{
    _text = title.string;
    [self setNeedsDisplay];
}

@end

1 Ответ

0 голосов
/ 13 февраля 2020

В конце я решил проблему с помощью автоматического макета.

Вместо того, чтобы использовать метод setBounds, я использую вычисленный размер, чтобы установить высоту и ширину кнопок с ограничениями.

Это новый код:

#import "RoundedButton.h"

@interface RoundedButton()
@property (nonatomic, retain) NSString *text;
@end

@implementation RoundedButton

-(void)awakeFromNib{
    [super awakeFromNib];
    _text = self.currentTitle;
    [super setTitle:@"" forState:UIControlStateNormal];

    [self setConstraint];
}

- (void)setConstraint {
    NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    style.alignment = NSTextAlignmentCenter;

    NSDictionary <NSString *, id>*attr = @{  NSFontAttributeName:self.titleLabel.font, NSParagraphStyleAttributeName:style };
    CGRect r = self.bounds;
    r.size = [_text sizeWithAttributes:attr];
    r.size.width += 20;
    r.size.height += 20;

    r.size.width = MAX( r.size.width, 200 );
    r.size.height = MAX( r.size.height, 40 );

    [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:r.size.width]];

    [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:r.size.height]];
}

-(void)layoutSubviews{
    [super layoutSubviews];
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    if ( ![self.backgroundColor isEqual:[UIColor clearColor]] ){
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:_cornerRounded];

        CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
        [bezierPath fill];


        //CGContextSetBlendMode(context, kCGBlendModeCopy);
        //CGContextFillRect(context, self.bounds);
        CGContextSetBlendMode(context, kCGBlendModeClear);

        NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
        style.alignment = NSTextAlignmentCenter;

        NSDictionary <NSString *, id>*attr = @{  NSFontAttributeName:self.titleLabel.font, NSParagraphStyleAttributeName:style };

        CGSize szText = [_text sizeWithAttributes:attr];

        CGRect r = self.bounds;
        r.origin.y += (r.size.height - szText.height)/2;

        [_text drawInRect:r withAttributes:attr];
    }
}

-(void)setEnabled:(BOOL)enabled{
    [super setEnabled:enabled];
    if ( !enabled ){
        self.alpha = 0.8;
    }
    else{
        self.alpha = 1.0;
    }
}

-(void)setTitle:(NSString *)title forState:(UIControlState)state{
    _text = title;
    [self setConstraint];
}


-(void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state{
    _text = title.string;
    [self setConstraint];
}

@end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...