有個需求是這樣的,有一個lable在一個button點擊后,內(nèi)容發(fā)生改變,相關(guān)尺寸也要發(fā)生改變,想要那個點擊的buton位置跟隨lable的位置發(fā)生同步變化。
開始的思路是在button點擊執(zhí)行的方法中更新相關(guān)約束,位置更新的沒有達到想要的效果。就是lable的text屬性改變后,button的位置約束就更新了,而現(xiàn)在的lable的bounds還沒有變化,或者變化沒有完成。這樣button相對的更新的位置就是沒有完全更新完的lable的位置為基準。所以沒有達到效果。
這個時候想著換用添加觀察者模式,當lable的bounds發(fā)生改變后,button的相對約束再更新。由于lable是系統(tǒng)空間,不方便直接增加功能。我這邊選擇一個比較好實現(xiàn)的方式,從新創(chuàng)建一個類繼承自UILable,在自定義lable初始化的方式中添加觀察者,觀察bounds屬性的變化,這時候效果達到了要求。下面是相關(guān)代碼實現(xiàn):
在實現(xiàn)上面的想法使用了block作為屬性,因為功能單一,使用delegate有點大材小用,也不方便。
***** MyLable.h文件 *****
#import <UIKit/UIKit.h>
@interface MyLable : UILabel
//下面定義了block屬性,確定當lable的bounds屬性發(fā)生改變后將要做什么操作
@property (nonatomic,copy) void (^change)();
@end
***** MyLable.m文件 *****
#import "MyLable.h"
@implementation MyLable
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
//稍微對標簽做了下美化,有圓角
self.layer.cornerRadius = 5;
self.layer.masksToBounds = YES;
//添加對bounds屬性的觀察
[self addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew||NSKeyValueChangeOldKey context:nil];
}
//實現(xiàn)觀察者模式需要實現(xiàn)的方法,調(diào)用改變后定義的block屬性,做到改變后,
//完成需要的相關(guān)動作
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
self.change();
NSLog(@"%@",change);
}
//注意在這個方法中移除觀察者,不然會發(fā)生錯誤。
-(void)dealloc{
[self removeObserver:self forKeyPath:@"bounds"];
}
@end
下面是viewController.m
方法
//中間約束使用了Masonry第三方庫,比較方便。可以使用cocopods導(dǎo)入到項目中使用。
#import "ViewController.h"
#import <Masonry/Masonry.h>
#import "MyLable.h"
@interface ViewController ()
//因為需要在更新位置,使用到控件,便放到屬性,方便使用
@property (nonatomic,strong)MyLable* lb;
@property (nonatomic,strong)UIButton* bt;
//這個是為了點擊后,有不同的效果,設(shè)置的一個變量
@property (nonatomic) BOOL ag;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.ag = YES;
MyLable* lable = [[MyLable alloc]init];
lable.lineBreakMode = NSLineBreakByWordWrapping;
lable.numberOfLines = 0;
lable.text = @"這世界很復(fù)雜,混淆我想說的話我不懂,太復(fù)雜的玩法,什么樣的禮物,能夠永遠記得住讓幸福別走的太倉促,云和天,蝶和花,從來不需要說話,斷不了依然日夜牽掛唱情歌,說情話,只想讓你聽清楚,我愛你是唯一的傾訴";
lable.font = [UIFont systemFontOfSize:18];
lable.textColor = [UIColor redColor];
lable.backgroundColor = [UIColor grayColor];
self.lb = lable;
float scw = [[UIScreen mainScreen]bounds].size.width;
[self.view addSubview:lable];
[self.lb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(40);
make.width.mas_equalTo(scw-scw/4);
make.centerX.mas_equalTo(0);
}];
//用這個方法實現(xiàn)button的添加,可以達到在lable完成之后,button的相對位置才能正確。
[self performSelectorOnMainThread:@selector(addButton) withObject:nil waitUntilDone:NO];
}
-(void)addButton{
UIButton* button =[UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"點擊" forState:UIControlStateNormal];
//為button添加點擊響應(yīng)方法,在響應(yīng)方法中確定約束更新。
[button addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor grayColor];
self.bt = button;
self.bt.titleLabel.textColor = [UIColor blackColor];
//避免循環(huán)引用的問題,為我自定義的MyLable對象的block屬性實現(xiàn)方法。
__block typeof(self) weakself = self;
self.lb.change = ^(){
[weakself.bt mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.lb.bounds.size.height+50);
make.centerX.mas_equalTo(0);
}];
};
self.bt.layer.cornerRadius = 10;
self.bt.layer.masksToBounds = YES;
[self.view addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.lb.bounds.size.height+50);
make.width.mas_equalTo(100);
make.centerX.mas_equalTo(0);
}];
}
-(void)click{
self.ag = !self.ag;
if (self.ag) {
self.lb.text = @"我是第二個內(nèi)容,我已經(jīng)變化了";
}else{
self.lb.text = @"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢噢uuuuuuuuuuuuuuuuuuuuuuuuuuuu";
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
好了,到這里,這個需求已經(jīng)能滿足了。其他更好的辦法還沒有想到,想到了再更新,如果有哪個高手有更好的方式,可以給我留言。