iOS Auto Layout Study Notes

GitHub原文

1、What's Auto Layout

Auto Layout是由蘋果公司UIKit框架提供的一個(gè)用于動(dòng)態(tài)計(jì)算UIView及其子類的大小和位置的庫(kù)胳蛮。

說到Auto Layout就不得不說Cassowary算法虐唠,因?yàn)?code>Auto Layout是構(gòu)建在Cassowary算法的基礎(chǔ)之上的讯榕。1997年蚊惯,Auto Layout用到的布局算法論文發(fā)表吆倦,被稱為高效的線性方程求解算法。2011年蘋果利用Cassowary算法為開發(fā)者提供了Auto Layout自動(dòng)布局庫(kù)中抄瓦。由于Cassowary算法的本身的優(yōu)秀潮瓶,不僅是蘋果公司,許多開發(fā)者將其運(yùn)用到各個(gè)不同的開發(fā)語言中钙姊,如JavaScript毯辅、ASP.NET、Java煞额、C++等都有運(yùn)用Cassowary算法的庫(kù)思恐。從這里也可以看出Cassowary算法自身的優(yōu)秀和先進(jìn)性沾谜,不然不會(huì)被運(yùn)用的如此廣泛。

蘋果公司在iOS 6系統(tǒng)時(shí)引入了Auto Layout胀莹,但是直到現(xiàn)在已經(jīng)更新到iOS 12了基跑,還有很多開發(fā)者還是不愿使用Auto Layout。主要是對(duì)其反人類的語法以及對(duì)其性能問題的擔(dān)憂嗜逻。

針對(duì)Auto Layout的一些問題涩僻,在iOS 9發(fā)布時(shí),蘋果推出了更簡(jiǎn)潔語法的NSLayoutAnchor栈顷。同時(shí)發(fā)布了模仿前端Flexbox布局思路的UIStackView,以此為開發(fā)者在自動(dòng)布局上提供更好的選擇嵌巷。

在蘋果WWDC 2018 High Performance Auto Layout中蘋果工程師說: iOS 12將大幅度提升Auto Layout性能萄凤,使滑動(dòng)屏幕時(shí)達(dá)到滿幀。
WWDC 2018 What's New in Cocoa Touch蘋果的工程師說了iOS 12對(duì)Auto Layout優(yōu)化后的表現(xiàn)搪哪。

WWDC 2018 What's New in Cocoa Touch

從圖上可以看出靡努,iOS 11中視圖嵌套的數(shù)量的性能快成指數(shù)級(jí)別增長(zhǎng)了,在iOS 12中已經(jīng)基本和手寫frame布局的性能類似了晓折。

iOS 6iOS 12惑朦,蘋果也在不斷的優(yōu)化Auto Layout的性能,同時(shí)為開發(fā)者提供更簡(jiǎn)潔的API漓概,如果你還在使用frame手寫布局漾月,不妨試試Auto Layout。下面我將介紹iOS中幾種常用的布局方法胃珍。

2梁肿、Auto Layout各個(gè)版本不同用法

如我要設(shè)置一個(gè)寬高為120,居中顯示的View,效果如下圖:


AutoLayoutdemo3.png
1觅彰、用frame手寫布局
    UIView *centerView = [[UIView alloc] init];
    centerView.backgroundColor = [UIColor redColor];
    [self.view addSubview:centerView];
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height;
    [centerView setFrame:CGRectMake(width / 2 - (60), height / 2 - (60), 120, 120)];
2吩蔑、iOS 6提供的NSLayoutConstraint語法添加約束
   centerView.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *consW = [NSLayoutConstraint constraintWithItem:centerView
                                                             attribute:NSLayoutAttributeWidth
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:self.view
                                                             attribute:NSLayoutAttributeWidth
                                                            multiplier:0
                                                              constant:120.0
                                 ];
    NSLayoutConstraint *consH = [NSLayoutConstraint constraintWithItem:centerView
                                                             attribute:NSLayoutAttributeHeight
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:self.view attribute:NSLayoutAttributeHeight
                                                            multiplier:0
                                                              constant:120.0
                                 ];
    NSLayoutConstraint *consX = [NSLayoutConstraint constraintWithItem:centerView
                                                             attribute:NSLayoutAttributeCenterX
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:self.view
                                                             attribute:NSLayoutAttributeCenterX
                                                            multiplier:1.0
                                                              constant:0.0
                                 ];
    NSLayoutConstraint *consY = [NSLayoutConstraint constraintWithItem:centerView
                                                             attribute:NSLayoutAttributeCenterY
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:self.view
                                                             attribute:NSLayoutAttributeCenterY
                                                            multiplier:1.0
                                                              constant:0.0
                                 ];
    [self.view addConstraints:@[consW,consH,consX,consY]];

3、用VFL語法
 centerView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[centerView(120)]" options:0 metrics:nil views:views]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[centerView(120)]" options:0 metrics:nil views:views]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
4填抬、使用第三方開源框架MasonrySnapKit
 __weak typeof (self) weakSelf = self;
 [centerView mas_makeConstraints:^(MASConstraintMaker *make) {
     make.size.mas_equalTo(CGSizeMake(120, 120));
     make.center.equalTo(weakSelf.view);
 }];

 let centerView:UIView = UIView.init()
 view.addSubview(centerView)
 centerView.backgroundColor = UIColor.red
 centerView.snp.makeConstraints { (make) in
    make.width.equalTo(120)
    make.height.equalTo(120)
    make.center.equalTo(view)
 }
5烛芬、使用iOS 9之后Apple提供的NSLayoutAnchor
 let centerView:UIView = UIView.init()
 view.addSubview(centerView)
 centerView.backgroundColor = UIColor.red
 centerView.translatesAutoresizingMaskIntoConstraints = false
 centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
 centerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
 centerView.widthAnchor.constraint(equalToConstant: 120).isActive = true
 centerView.heightAnchor.constraint(equalToConstant: 120).isActive = true

通過上面的代碼對(duì)比,使用frame手寫布局只要幾行代碼就搞定了飒责,使用NSLayoutConstraint語法和VFL語法是最復(fù)雜的赘娄,尤其是NSLayoutConstraint語法要用30多行代碼才能是想同樣的效果,代碼行數(shù)越多出錯(cuò)的概率也就成正比上升读拆,所以這就是很多開發(fā)者不愿使用Auto Layout(或者說不愿意使用系統(tǒng)提供API來實(shí)現(xiàn))的原因之一吧擅憔。

如果你的App要兼容iOS 9以下的各個(gè)版本,建議使用Masonry,如果只兼容iOS 9以上的版本檐晕,建議使用SnapKit或者系統(tǒng)提供的NSLayoutAnchor API暑诸,畢竟Masonry這個(gè)庫(kù)已經(jīng)2年沒有更新了蚌讼。

在這里我推薦優(yōu)先使用NSLayoutAnchor,第三方的開源庫(kù)隨時(shí)都面臨著一些問題:

  • iOS 系統(tǒng)版本的更新造成的適配和兼容問題个榕,如果是開源代碼要等到蘋果發(fā)布新版本篡石,代碼的作者再做兼容和適配
  • 代碼的作者停止更新這些代碼了,這對(duì)我們開發(fā)者來說就很被動(dòng)了西采,我們要么自己修改這些代碼凰萨,要么選擇更新的開源代碼
  • 使用系統(tǒng)庫(kù)可在打包時(shí)可以減少包大小

3、Auto Layout的生命周期

前面說到蘋果的Auto Layout是基于Cassowary算法的械馆,蘋果在此基礎(chǔ)上提供了一套Layout Engine引擎胖眷,由它來管理頁面的布局,來完成創(chuàng)建霹崎、更新珊搀、銷毀等。

APP啟動(dòng)后尾菇,會(huì)開啟一個(gè)常駐線程來監(jiān)聽約束變化境析,當(dāng)約束發(fā)生變化后會(huì)出發(fā)Deffered Layout Pass(延遲布局傳遞),在里面做容錯(cuò)處理(如有些視圖在更新約束時(shí)沒有確定或缺失布局申明)派诬,完成后進(jìn)入約束監(jiān)聽變化的狀態(tài)劳淆。

當(dāng)下一次刷新視圖(如調(diào)用layoutIfNeeded())時(shí),Layout Engine會(huì)從上到下調(diào)用layoutSubviews()默赂,然后通過Cassowary算法計(jì)算各個(gè)子視圖的大小和位置沛鸵,算出來后將子視圖的framelayout Engine里拷貝出來,在之后的處理就和手寫frame的繪制放可、渲染的過程一樣了谒臼。使用Auto Layout和手寫frame多的工作就在布局計(jì)算上。

4耀里、NSLayoutAnchor常用屬性

  • leadingAnchor
  • trailingAnchor
  • leftAnchor
  • rightAnchor
  • topAnchor
  • bottomAnchor
  • widthAnchor
  • heightAnchor
  • centerXAnchor
  • centerYAnchor
  • firstBaselineAnchor
  • lastBaselineAnchor

對(duì)于NSLayoutAnchor的一些常用屬性蜈缤,通過其命名就能看出來其作用,這里不做贅述冯挎,如果想了解更多請(qǐng)查閱Apple Developer NSLayoutAnchor底哥。

5、Auto Layout幾個(gè)更新約束的方法

  • setNeedsLayout: 告知頁面需要更新房官,但是不會(huì)立刻開始更新趾徽。執(zhí)行后會(huì)立刻調(diào)用layoutSubviews

  • layoutIfNeeded: 告知頁面布局立刻更新翰守。所以一般都會(huì)和setNeedsLayout一起使用孵奶。如果希望立刻生成新的frame需要調(diào)用此方法,利用這點(diǎn)一般布局動(dòng)畫可以在更新布局后直接使用這個(gè)方法讓動(dòng)畫生效蜡峰。

  • layoutSubviews: 更新子View約束

  • setNeedsUpdateConstraints:需要更新約束了袁,但是不會(huì)立刻開始

  • updateConstraintsIfNeeded:立刻更新約束

  • updateConstraints:更新View約束

6朗恳、NSLayoutAnchor使用注意事項(xiàng)

  • 1、在使用NSLayoutAnchor為視圖添加約束時(shí)一定要先把translatesAutoresizingMaskIntoConstraints設(shè)置false
 centerView.translatesAutoresizingMaskIntoConstraints = false
  • 2载绿、在使用safeAreaLayoutGuide適配iPhone X 等機(jī)型時(shí)要對(duì)iOS 11之前的系統(tǒng)做適配粥诫,否則會(huì)導(dǎo)致低版本系統(tǒng)上程序Crash
if #available(iOS 11.0, *) {
     tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
 } else {
     tableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
 }
  • 3、設(shè)置約束后要將其激活崭庸,即設(shè)置isActivetrue
let centerX: NSLayoutConstraint = centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0)
centerX.isActive = true
  • 4怀浆、leadingAnchor 不要和 leftAnchor混用
centerView.leadingAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
centerView.leftAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true

以上2種寫法,在編譯時(shí)不會(huì)出現(xiàn)任何問題怕享,但是在運(yùn)行時(shí)就會(huì)報(bào)錯(cuò)执赡,并會(huì)導(dǎo)致程序Crash,官方的說法是:

While the NSLayoutAnchor class provides additional type checking, it is still possible to create 
invalid constraints. For example, the compiler allows you to constrain one view’s leadingAnchor
 with another view’s leftAnchor, since they are both NSLayoutXAxisAnchor instances. However, 
Auto Layout does not allow constraints that mix leading and trailing attributes with left or right 
attributes. As a result, this constraint crashes at runtime.

同理,trailingAnchorrightAnchor也不能混用函筋。

  • 5搀玖、如何刷新某個(gè)約束

如我要修改一個(gè)UIView的寬度:
通過代碼添加約束,可把UIView的寬度設(shè)置類屬性驻呐,然后在需要的地方修改constant的參數(shù),然后在刷新約束即可芳来,代碼如下:

 var centerView: UIView! 
 var centerWidth: NSLayoutConstraint! 


self.centerView = UIView.init()
view.addSubview(self.centerView)
self.centerView.backgroundColor = UIColor.red
self.centerView.translatesAutoresizingMaskIntoConstraints = false
self.centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
self.centerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
self.centerWidth = self.centerView.widthAnchor.constraint(equalToConstant: 120)
self.centerWidth.isActive = true
self.centerView.heightAnchor.constraint(equalToConstant: 120).isActive = true
self.centerWidth.constant = 250
UIView.animate(withDuration: 0.35, animations: { [weak self] in
            guard let `self` = self else { return }
   self.centerView.superview?.layoutIfNeeded()
}) { (finished) in
            
}

效果如下:


layoutDemo5.gif

如果是xib或者storyboard含末,那就更簡(jiǎn)單了,直接摁住鍵盤control鍵即舌,拖到對(duì)應(yīng)的類里佣盒,然后在需要的地方修改約束并刷新即可。操作如下:

AutoLayoutdemo6.gif

  • 6顽聂、設(shè)置寬高比

在開發(fā)中肥惭,我們會(huì)遇到一些需求要求根據(jù)UIView的寬高比來設(shè)置約束,如一般情況下顯示視頻的寬高比是16:9紊搪,通過代碼設(shè)置寬高比如下:

 centerView.heightAnchor.constraint(equalToConstant: 90).isActive = true
 centerView.widthAnchor.constraint(equalTo: centerView.heightAnchor, multiplier: 16 / 9).isActive = true
layoutDemo7.png

7蜜葱、Auto Layout自適應(yīng)UITableViewCell高度使用

  • 使用rowHeight設(shè)置高度

一般情況下,如果UITableView的每個(gè)Cell高度是固定的我們可以直接指定一個(gè)值即可耀石,如果沒有設(shè)置UITableView的高度牵囤,系統(tǒng)會(huì)默認(rèn)設(shè)置rowHeight高度是44。

tableview.rowHeight = 44;

也可以通過UITableViewDelegate的代理來設(shè)置UItableView的高度滞伟。

 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 50
 }

如果通過手動(dòng)計(jì)算每個(gè)UItableViewCell的高度揭鳞,也在這個(gè)代理中實(shí)現(xiàn),通過計(jì)算返回每個(gè)UItableViewCell的高度梆奈。

  • 使用estimatedRowHeight設(shè)置高度

UItableView繼承自UIScrollView,UIScrollView的滾動(dòng)需要設(shè)置其contentSize后野崇,然后根據(jù)自身的bounds、contentInset亩钟、contentOffset等屬性來計(jì)算出可滾動(dòng)的長(zhǎng)度乓梨。而UITableView在初始化時(shí)并不知道這些參數(shù)鳖轰,只有在設(shè)置了delegatedataSource之后,根據(jù)創(chuàng)建的UITableViewCell的個(gè)數(shù)和加載的UITableViewCell的高度之后才能算出可滾動(dòng)的長(zhǎng)度。

在使用Auto Layout自適應(yīng)UITableViewCell高度時(shí)應(yīng)提前設(shè)置一個(gè)估算值,當(dāng)然這個(gè)估算值越接近真實(shí)值越好抵屿。

 tableView.rowHeight = UITableView.automaticDimension
 tableView.estimatedRowHeight = 200
 func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return 200    
 }
Autolayoutdemo2.png

如上圖所示:這個(gè)界面就是用Auto Layout + estimatedRowHeight完成自適應(yīng)高度的仪壮,在添加約束時(shí)要按照從上到下的書訊設(shè)置每一個(gè)UIView的頂部(top)到上一個(gè)的視圖底部的(bottom)距離,同時(shí)要計(jì)算UITableViewCell內(nèi)部所有控件的高度痴怨。那么問題來了,用戶發(fā)布的內(nèi)容詳情沒有得到數(shù)據(jù)之前時(shí)沒辦法算出其高度的,此處可以先給內(nèi)容文字UILabel設(shè)置一個(gè)默認(rèn)高度忆肾,然后讓其根據(jù)內(nèi)容填充自動(dòng)計(jì)算高度:

 topicInfoLab.heightAnchor.constraint(greaterThanOrEqualToConstant: 20).isActive = true;
 topicInfoLab.font = UIFont.init(name: "Montserrat-SemiBold", size: 12)
topicInfoLab.numberOfLines = 0

如果用戶發(fā)布內(nèi)容沒有圖片,直接設(shè)置發(fā)布內(nèi)容UILabel距離UITableView距離底部的約束距離即可菱肖;

 detailsLab.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true

如果用戶發(fā)布的內(nèi)容有圖片客冈,那么在計(jì)算出每張圖片的位置和大小之后,一定要給最后一張圖片設(shè)置距離UItableViewCell底部(bottom)的約束距離稳强。

for(idx, obj) in imageArray.enumerated() {
//.....計(jì)算圖片的大小和位置
if idx == imageArray.count - 1 {
   //設(shè)置最后一張圖片距離底部的約束
   photo.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true
 }
}
layoutDemo8.png

實(shí)現(xiàn)思路如上圖所示场仲,具體實(shí)現(xiàn)的請(qǐng)看代碼

8、 Compression Resistance PriorityHugging Priority使用

Compression Resistance PriorityHugging Priority在實(shí)際使用中往往配合使用退疫,分別處理在同義水平線上多個(gè)view之間內(nèi)容過少和內(nèi)容過多而造成的互相壓擠的情況渠缕。

Hugging Priority的意思就是自包裹的優(yōu)先級(jí),優(yōu)先級(jí)越高褒繁,則優(yōu)先將尺寸按照控件的內(nèi)容進(jìn)行填充亦鳞。

Compression Resistance Priority,意思是說當(dāng)不夠顯示內(nèi)容時(shí)棒坏,根據(jù)這個(gè)優(yōu)先級(jí)進(jìn)行切割燕差。優(yōu)先級(jí)越低,越容易被切掉坝冕。

ContentHuggingPriority 表示當(dāng)前的UIView的內(nèi)容不想被拉伸
ContentCompressionResistancePriority 表示當(dāng)前的UIView的內(nèi)容不想被收縮
默認(rèn)情況下: HuggingPriority = 250 默認(rèn)情況下: CompressionResistancePriority = 750

如設(shè)置2個(gè)UILabel的拉伸優(yōu)先級(jí)可使用代碼:

fristLab.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .horizontal)
secondLab.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 750), for: .horizontal)

9徒探、總結(jié)

本文主要分享了蘋果Auto Layout的幾種實(shí)現(xiàn)方法和注意事項(xiàng),對(duì)于Auto Layout在實(shí)際開發(fā)中的使用是采用純代碼徽诲、還是xib + 代碼刹帕,還是storyboard + 代碼,還是xib + storyboard + 代碼的方式實(shí)現(xiàn)谎替,主要看團(tuán)隊(duì)的要求偷溺、個(gè)人的習(xí)慣,以及App的繁瑣程度钱贯。
對(duì)于Auto Layout在視圖上的使用挫掏,個(gè)人建議如果UI比較簡(jiǎn)單或者單一的界面可使用Auto Layout,如果UI的操作或刷新很復(fù)雜的界面秩命,建議還是frame + 手動(dòng)布局的方式尉共。


本文demo褒傅,請(qǐng)戳這里
本文參考:
深入剖析Auto Layout,分析iOS各版本新增特性
Auto Layout 是怎么進(jìn)行自動(dòng)布局的袄友,性能如何殿托?
Apple Developer High Performance Auto Layout
Apple Develope NSLayoutConstraint
WWDC 2018 What's New in Cocoa Touch

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市剧蚣,隨后出現(xiàn)的幾起案子支竹,更是在濱河造成了極大的恐慌,老刑警劉巖鸠按,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件礼搁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡目尖,警方通過查閱死者的電腦和手機(jī)馒吴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑟曲,“玉大人饮戳,你說我怎么就攤上這事《床Γ” “怎么了莹捡?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)扣甲。 經(jīng)常有香客問我,道長(zhǎng)齿椅,這世上最難降的妖魔是什么琉挖? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮涣脚,結(jié)果婚禮上示辈,老公的妹妹穿的比我還像新娘。我一直安慰自己遣蚀,他們只是感情好矾麻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芭梯,像睡著了一般险耀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玖喘,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天甩牺,我揣著相機(jī)與錄音,去河邊找鬼累奈。 笑死贬派,一個(gè)胖子當(dāng)著我的面吹牛急但,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搞乏,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼波桩,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了请敦?” 一聲冷哼從身側(cè)響起镐躲,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冬三,沒想到半個(gè)月后匀油,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勾笆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年敌蚜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窝爪。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弛车,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蒲每,到底是詐尸還是另有隱情纷跛,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布邀杏,位于F島的核電站贫奠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏望蜡。R本人自食惡果不足惜唤崭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脖律。 院中可真熱鬧谢肾,春花似錦、人聲如沸小泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽微姊。三九已至酸茴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兢交,已是汗流浹背弊决。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人飘诗。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓与倡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親昆稿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纺座,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • 先前寫到的一篇Masonry心得文章里已經(jīng)提到了很多AutoLayout相關(guān)的知識(shí)净响,這篇我會(huì)更加詳細(xì)的對(duì)其知識(shí)要點(diǎn)...
    星光社的戴銘閱讀 7,548評(píng)論 5 61
  • 寫在前面 iOS的的布局機(jī)制「auto layout」不是一個(gè)新概念,它早在iOS 6中就推出來了喳瓣,當(dāng)下距離iOS...
    西門淋雨閱讀 1,508評(píng)論 2 4
  • 如果有一天 我們變成螞蟻般大小 我們的世界會(huì)不會(huì)是這樣子馋贤?
    加零點(diǎn)一閱讀 959評(píng)論 12 12
  • 前言:職場(chǎng)如戰(zhàn)場(chǎng),老生常談卻又經(jīng)久不衰的話題畏陕。相關(guān)文章業(yè)已不知凡幾配乓。然而,大道理講得多惠毁,可借鑒的經(jīng)驗(yàn)不足犹芹,欠缺可操...
    五月睿陽閱讀 341評(píng)論 0 0