An app I'm working on has a customized UIButton class that is supposed to create a rounded button of a size depending on its title.
From when I've updated to iOS 13, something strange is happening:
the first time the view containing these buttons appears, everything works well. Then I segue to another view controller, then go back to the view with the buttons and here I get an infinite loop on the -layoutsubviews method.
This is the customized class:
#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
At the end I've solved the problem using auto layout.
Instead of using the
setBoundsmethod, I'm using the calculated size to set the height and width of the buttons with constraints.This is the new code: