在使用xib自定義view的時候,個人習慣性的直接使用xib中的約束,所以自然而然的要打開Autolayout。以前在使用的時候沒有發現什么問題,最近項目中使用的時候突然發現在導航欄透明的情況下,出現實際的frame比設置的frame高度縮小64的問題,然后上網查找各種博客,最后差點被五花八門的寫法帶跑偏了,遂簡單記錄一下正確的解決方式。
自定義方法大致如下:
1、xib 和TestXibView是綁定的
2、xib中如下圖:(Autolayout開啟的)
3、TestXibView.m中主要代碼如下:(是使用等號定義的)
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor redColor]; NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"TestXibView" owner:nil options:nil]; self = xib.lastObject;//注意這里我使用的是“=” self.frame = frame; } return self; } - (void)awakeFromNib{ [super awakeFromNib]; }
問題:
正常情況下在控制器的view中添加TestXibView實例view的時候是沒有問題的,
但是當我需要設置導航欄不透明的時候,需要用到這句代碼:
self.navigationController.navigationBar.translucent = NO;
這時,問題出現,問題如下:(僅在控制器view是UIView類型的時候才會出現,當xib view添加到滾動視圖上時不會有下面的問題)
1、添加的view高度會縮減64
2、同時控制台會打印約束沖突的情況
注意:(親測automaticallyAdjustsScrollViewInsets,self.extendedLayoutIncludesOpaqueBars,edgesForExtendedLayout這些設置都解決不了這個問題)
解決辦法1:(偏門)
最初在沒有找到造成這種問題的原因的情況下,我只能把設置frame的相關demo寫在這個方法中viewDidLayoutSubviews,雖然用着別扭,但是至少可以臨時解決問題。
- (void)viewDidLayoutSubviews{ [super viewDidLayoutSubviews]; }
解決辦法2、關閉Autoresize SubViews(正解)
控制器中的Autoresize SubViews不勾選
或者在viewdidload方法中添加下面代碼,也能起到相同的效果:
self.view.autoresizesSubviews = NO;
問題的分析:
其實造成xib view高度縮小64像素以及會打印約束沖突的最根本原因是,我們在Xcode9上創建xib或者storyboard文件時,會默認打開Autoresize SubViews,所以在設置導航欄透明的時候,因為自動重新布局之后導致高度縮小,原來的xib中的約束無效。
既然問題查清楚了,那就對症下葯,關閉Autoresize SubViews即可。
其實自己寫的代碼,出錯了,網上的很多辦法只能是參考,因為錯誤的前提或者環境可能差別很大,所以,出現bug時,首先仔細認真的檢查自己的代碼是否存在問題,在確保沒問題(或者自己沒有找到問題)的情況下可以去參考網上的一些解決辦法。但是最終還是要對症下葯,了解病症所在才能真正的解決辦法。
其它贅述:當然在xib不綁定TextXibView情況下,直接使用xib,也就是下面的方法
NSArray *arr=[[NSBundle mainBundle]loadNibNamed:@"TestXibView" owner:nil options:nil]; UIView *tmpView = arr.lastObject; tmpView.frame = CGRectMake(0, 300, 100, 100); [self.view addSubview:tmpView];