iOS (5) --Block

<h1>1酥馍、Block底層原理實(shí)現(xiàn)</h1>

首先我們來(lái)看四個(gè)函數(shù)

void test1()
{
    int a = 10;

    void (^block)() = ^{
        NSLog(@"a is %d", a);
    };

    a = 20;

    block(); // 10
}

void test2()
{
    __block int a = 10;

    void (^block)() = ^{
        NSLog(@"a is %d", a);
    };

    a = 20;

    block(); // 20
}

void test3()
{
    static int a = 10;

    void (^block)() = ^{
        NSLog(@"a is %d", a);
    };

    a = 20;

    block(); // 20
}

int a = 10;
void test4()
{
    void (^block)() = ^{
        NSLog(@"a is %d", a);
    };

    a = 20;

    block();//20
}

造成這樣的原因是:傳值和傳址故慈。為什么說(shuō)會(huì)有傳值和傳址板熊,把.m編譯成c++代碼。得到.cpp文件察绷,我們來(lái)到文件的最后干签,看到如下代碼

struct __test1_block_impl_0 {
    struct __block_impl impl;
    struct __test1_block_desc_0* Desc;
    int a;
    __test1_block_impl_0(void *fp,struct __test1_block_desc_0* Desc,int _a,int flag=0): a(_a){
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
    }
};

static void __test1_block_func_0(struct __test1_block_imp_0 *__cself)
{
    int a = __cself->a;
    NSLog(a);//這里就是打印a的值,代碼太長(zhǎng)拆撼,而且沒(méi)意義容劳,我就不敲出來(lái)了。
}

void test1()
{
    int a = 10;
    void (*block)() = (void (*)())&__test1_block_impl_0((void *))__test1_block_func_0,&__test1_block_desc_0_DATA,a);

    a = 20;
    ((void (*)(__block_impl *))((__block_ipml *)block)->FuncPtr)((_block_impl *)block);
}

int main(int argc, const char * argv[])
{
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;         
       test1();
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

我們看到void test1()中闸度,void (*block)() 右邊最后面 竭贩,把a(bǔ)傳進(jìn)去了,也就是把10這個(gè)值傳進(jìn)去了.

而且對(duì)void (block)()簡(jiǎn)化分析莺禁,void (block)() = &__test1_block_impl_0();所以block就是指向結(jié)構(gòu)體的指針留量。

10傳入block后,代碼最上面創(chuàng)建的__test1_block_impl_0結(jié)構(gòu)體中哟冬,a = 10楼熄;

對(duì)void test1()中最下面的函數(shù)進(jìn)行簡(jiǎn)化分析,得到(block)->FuncPtr)(block)柒傻,我們?cè)诨氐絼偛?em>test1_block_impl_0這個(gè)結(jié)構(gòu)體中孝赫,impl.FuncPtr = fp;而fp又是傳入結(jié)構(gòu)體的第一個(gè)參數(shù),而在void (block)()中红符,傳入結(jié)構(gòu)體的第一個(gè)參數(shù)為*test1_block_func_0青柄,也就是說(shuō)(block)->FuncPtr)(block) =》__test1_block_func_0(block);

上一步相當(dāng)于調(diào)用test1_block_func_0()這個(gè)函數(shù),我們來(lái)看這個(gè)函數(shù)预侯,有這樣一段代碼:int a = cself->a;訪問(wèn)block中的a值致开,傳遞給a;所以是10.這種就是傳值N凇K痢!

=====
我們?cè)賮?lái)看test2( );添加了__block會(huì)發(fā)送什么變化呢

void test2()
{
    __attribute__((_blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a,0,sizeof(__Block_byref_a_0),10};

    void(*block)() =  (void (*)())&__test2_block_impl_0((void *))__test2_block_func_0,&__test2_block_desc_0_DATA,(__Block_byref_a_0 *)&a,570425344);

    (a.__forwarding->a) = 20;

    ((void (*)(__block_impl *))((__block_ipml *)block)->FuncPtr)((_block_impl *)block);
}

int main(int argc, const char * argv[])
{
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;         
       test2();
    }
    return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

代碼雖然很多看著很復(fù)雜糜芳,但是我們只需要看我們想要知道的飒货,睜大你的眼睛魄衅,看到void(*block)()這個(gè)函數(shù)的最后面,有個(gè)&a,天啊塘辅,這里傳的是a的地址晃虫。從test2到test4,都是傳址扣墩,所以a的值發(fā)生改變哲银,block打印出來(lái)的是a的最終值。
總結(jié):只有普通局部變量是傳值呻惕,其他情況都是傳址荆责。

<h1>2、block的定義</h1>

// 無(wú)參無(wú)返回
void(^block)();
// 無(wú)參有返回
int(^block1)();
// 有參有返回
int(^block1)(int number);

也可以直接打入inline來(lái)自動(dòng)生成block格式

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
    <#statements#>
};

<h1>3亚脆、block的內(nèi)存管理</h1>

1> 無(wú)論當(dāng)前環(huán)境是ARC還是MRC,只要block沒(méi)有訪問(wèn)外部變量,block始終在全局區(qū)
2> MRC情況下
block如果訪問(wèn)外部變量,block在棧里
不能對(duì)block使用retain,否則不能保存在堆里
只有使用copy,才能放到堆里
3> ARC情況下
block如果訪問(wèn)外部變量,block在堆里
block可以使用copy和strong,并且block是一個(gè)對(duì)象

<h1>4做院、block的循環(huán)引用</h1>

如果要在block中直接使用外部強(qiáng)指針會(huì)發(fā)生錯(cuò)誤,使用以下代碼在block外部實(shí)現(xiàn)可以解決
__weak typeof(self) weakSelf = self;
但是如果在block內(nèi)部使用延時(shí)操作還使用弱指針的話會(huì)取不到該弱指針,需要在block內(nèi)部再將弱指針強(qiáng)引用一下
__strong typeof(self) strongSelf = weakSelf;

<h1>5、描述一個(gè)你遇到過(guò)的retain cycle例子濒持。</h1>

block中的循環(huán)引用:一個(gè)viewController
@property (nonatomic,strong)HttpRequestHandler * handler;    

@property (nonatomic,strong)NSData  *data;    
 _handler = [httpRequestHandler sharedManager];   
  [ downloadData:^(id responseData){     
_data = responseData;  
   }];
self 擁有_handler, _handler 擁有block, block擁有self(因?yàn)槭褂昧藄elf的_data屬性山憨,block會(huì)copy 一份self) 
解決方法:
__weak typedof(self)weakSelf = self  
 [ downloadData:^(id responseData){    
     weakSelf.data = responseData;

<h1>6、block中的weak self弥喉,是任何時(shí)候都需要加的么?</h1>

不是什么任何時(shí)候都需要添加的玛迄,不過(guò)任何時(shí)候都添加似乎總是好的由境。只要出現(xiàn)像self->block->self.property/self->_ivar這樣的結(jié)構(gòu)鏈時(shí),才會(huì)出現(xiàn)循環(huán)引用問(wèn)題蓖议。好好分析一下虏杰,就可以推斷出是否會(huì)有循環(huán)引用問(wèn)題。

<h1>7勒虾、通過(guò)block來(lái)傳值</h1>

在控制器間傳值可以使用代理或者block,使用block相對(duì)來(lái)說(shuō)簡(jiǎn)潔
在前一個(gè)控制器的touchesBegan:方法內(nèi)實(shí)現(xiàn)如下代碼

ModalViewController *modalVc = [[ModalViewController alloc] init];

  modalVc.valueBlcok = ^(NSString *str){

  NSLog(@"ViewController拿到%@",str);
  };

  [self presentViewController:modalVc animated:YES completion:nil];

在ModalViewController控制器的.h文件中聲明一個(gè)block屬性 @property (nonatomic ,strong) void(^valueBlcok)(NSString *str);

并在.m文件中實(shí)現(xiàn)方法

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 傳值:調(diào)用block
        if (_valueBlcok) {
        _valueBlcok(@"123");
        }
    }

這樣在ModalViewController回到上一個(gè)控制器的時(shí)候,上一個(gè)控制器的label就能顯示ModalViewController傳過(guò)來(lái)的字符串

<h1>8纺阔、block作為一個(gè)參數(shù)使用</h1>

新建一個(gè)類(lèi),在.h文件中聲明一個(gè)方法- (void)calculator:(int(^)(int result))block;

并在.m文件中實(shí)現(xiàn)該方法

  -(void)calculator:(int (^)(int))block
  {
  self.result = block(self.result);
  }

在其他類(lèi)中調(diào)用該方法

 CalculatorManager *mgr = [[CalculatorManager alloc] init];
  [mgr calculator:^(int result){
  result += 5;
  return result;
  }];

<h1>9、block作為返回值使用</h1>

在masonry框架中我們可以看到如下用法make.top.equalTo(superview.mas_top).with.offset(padding.top); 這個(gè)方法實(shí)現(xiàn)就是將block作為返回值來(lái)使用

來(lái)分析一下這段代碼:其實(shí)可以將這段代碼看成make.top,make.equalTo,make.with,make.offset,所以可以得出一個(gè)結(jié)論是make.top返回了一個(gè)make,才能實(shí)現(xiàn)make.top.equalTo

那來(lái)模仿一下這種功能的實(shí)現(xiàn)

新建一個(gè)類(lèi),在.h文件中聲明一個(gè)方法- (CalculatorManager *(^)(int a))add;

在.m文件中實(shí)現(xiàn)方法

  -(CalculatorManager * (^)(int a))add
  {
      return ^(int a){
          _result += a;
      return self;
  };
  }

這樣就可以在別的類(lèi)中實(shí)現(xiàn)上面代碼的用法

   mgr.add(1).add(2).add(3);

<h1>10修然、block的變量傳遞</h1>

如果block訪問(wèn)的外部變量是局部變量,那么就是值傳遞,外界改了,不會(huì)影響里面
如果block訪問(wèn)的外部變量是__block或者static修飾,或者是全局變量,那么就是指針傳遞,block里面的值和外界同一個(gè)變量,外界改變,里面也會(huì)改變
驗(yàn)證一下是不是這樣
通過(guò)Clang來(lái)將main.m文件編譯為C++
在終端輸入如下命令clang -rewrite-objc main.m

void(*block)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0,         &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
 void(*block)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0,        

可以看到在編譯后的代碼最后可以發(fā)現(xiàn)被__block修飾過(guò)得變量使用的是&a,而局部變量是a

<h1>11笛钝、block的注意點(diǎn)</h1>

在block內(nèi)部使用外部指針且會(huì)造成循環(huán)引用情況下,需要用__weak修飾外部指針

__weak typeof(self) weakSelf = self;

在block內(nèi)部如果調(diào)用了延時(shí)函數(shù)還使用弱指針會(huì)取不到該指針,因?yàn)橐呀?jīng)被銷(xiāo)毀了,需要在block內(nèi)部再將弱指針重新強(qiáng)引用一下

__strong typeof(self) strongSelf = weakSelf;

如果需要在block內(nèi)部改變外部變量的話,需要在用__block修飾外部變量
<h1>12、使用block有什么好處愕宋?使用NSTimer寫(xiě)出一個(gè)使用block顯示(在UILabel上)秒表的代碼。</h1>

說(shuō)到block的好處,最直接的就是代碼緊湊咧织,傳值萧豆、回調(diào)都很方便,省去了寫(xiě)代理的很多代碼邻寿。
對(duì)于這里根本沒(méi)有必要使用block來(lái)刷新UILabel顯示蝎土,因?yàn)槎际侵苯淤x值视哑。當(dāng)然,筆者覺(jué)得這是在考驗(yàn)應(yīng)聘者如何將NSTimer寫(xiě)成一個(gè)通用用的Block版本誊涯。
NSTimer封裝成Block版: http://www.henishuo.com/nstimer-block/
使用起來(lái)像這樣:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                    repeats:YES
                                   callback:^() {
  weakSelf.secondsLabel.text = ...
}
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

<h1>13挡毅、block跟函數(shù)很像:</h1>

可以保存代碼
有返回值
有形參
調(diào)用方式一樣

<h1>14、使用系統(tǒng)的某些block api(如UIView的block版本寫(xiě)動(dòng)畫(huà)時(shí))醋拧,是否也考慮引用循環(huán)問(wèn)題慷嗜?</h1>

系統(tǒng)的某些block api中,UIView的block版本寫(xiě)動(dòng)畫(huà)時(shí)不需要考慮丹壕,但也有一些api需要考慮庆械。所謂“引用循環(huán)”是指雙向的強(qiáng)引用,
所以那些“單向的強(qiáng)引用”(block 強(qiáng)引用 self )沒(méi)有問(wèn)題菌赖,比如這些:

[UIView animateWithDuration:duration animations:^{ [self.superview layoutIfNeeded]; }]; 
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.someProperty = xyz; }]; 
[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification" 
                           object:nil 
                           queue:[NSOperationQueue mainQueue]
                           usingBlock:^(NSNotification * notification) {
                           self.someProperty = xyz; 
                                                    }];

這些情況不需要考慮“引用循環(huán)”缭乘。
但如果你使用一些參數(shù)中可能含有成員變量的系統(tǒng)api,如GCD琉用、NSNotificationCenter就要小心一點(diǎn)堕绩。比如GCD內(nèi)部如果引用了 self,而且GCD的其他參數(shù)是成員變量邑时,則要考慮到循環(huán)引用:

__weak __typeof(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^{
    __typeof__(self) strongSelf = weakSelf;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
});

類(lèi)似的:

__weak __typeof(self) weakSelf = self;
_observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"
                                                            object:nil
                                                             queue:nil
                                                        usingBlock:^(NSNotification *note) {
  __typeof__(self) strongSelf = weakSelf;
  [strongSelf dismissModalViewControllerAnimated:YES];
}];
self –> _observer –> block –> self 顯然這也是一個(gè)循環(huán)引用奴紧。

<h1>15、談?wù)剬?duì)Block 的理解?并寫(xiě)出一個(gè)使用Block執(zhí)行UIVew動(dòng)畫(huà)?</h1>

Block是可以獲取其他函數(shù)局部變量的匿名函數(shù)晶丘,其不但方便開(kāi)發(fā)黍氮,并且可以大幅提高應(yīng)用的執(zhí)行效率(多核心CPU可直接處理Block指令)

[UIView transitionWithView:self.view duration:0.2
                                      ptions:UIViewAnimationOptionTransitionFlipFromLeft
                                      animations:^{ [[blueViewController view] removeFromSuperview]; [[self view] insertSubview:yellowViewController.view atIndex:0]; }
                                       completion:NULL];

<h1>16、寫(xiě)出上面代碼的Block的定義浅浮。</h1>

typedef void(^animations) (void);
typedef void(^completion) (BOOL finished);

<h1>17沫浆、什么是block</h1>

1> 對(duì)于閉包(block),有很多定義,其中閉包就是獲取其它函數(shù)局部變量的匿名函數(shù)滚秩,這個(gè)定義即接近本質(zhì)又較好理解专执。

2> 對(duì)于剛接觸Block的同學(xué),會(huì)覺(jué)得有些繞郁油,因?yàn)槲覀兞?xí)慣寫(xiě)這樣的程序main(){ funA();} funA(){funB();} funB(){…..}; 就是函數(shù)main調(diào)用函數(shù)A本股,函數(shù)A調(diào)用函數(shù)B… 函數(shù)們依次順序執(zhí)行,但現(xiàn)實(shí)中不全是這樣的已艰,例如項(xiàng)目經(jīng)理M痊末,手下有3個(gè)程序員A、B哩掺、C凿叠,當(dāng)他給程序員A安排實(shí)現(xiàn)功能F1時(shí),他并不等著A完成之后,再去安排B去實(shí)現(xiàn)F2盒件,而是安排給A功能F1蹬碧,B功能F2,C功能F3炒刁,然后可能去寫(xiě)技術(shù)文檔恩沽,而當(dāng)A遇到問(wèn)題時(shí),他會(huì)來(lái)找項(xiàng)目經(jīng)理M翔始,當(dāng)B做完時(shí)罗心,會(huì)通知M,這就是一個(gè)異步執(zhí)行的例子城瞎。

3> 在這種情形下渤闷,Block便可大顯身手,因?yàn)樵陧?xiàng)目經(jīng)理M脖镀,給A安排工作時(shí)飒箭,同時(shí)會(huì)告訴A若果遇到困難,如何能找到他報(bào)告問(wèn)題(例如打他手機(jī)號(hào))蜒灰,這就是項(xiàng)目經(jīng)理M給A的一個(gè)回調(diào)接口弦蹂,要回掉的操作,比如接到電話强窖,百度查詢(xún)后凸椿,返回網(wǎng)頁(yè)內(nèi)容給A,這就是一個(gè)Block翅溺,在M交待工作時(shí)削饵,已經(jīng)定義好,并且取得了F1的任務(wù)號(hào)(局部變量)未巫,卻是在當(dāng)A遇到問(wèn)題時(shí),才調(diào)用執(zhí)行启昧,跨函數(shù)在項(xiàng)目經(jīng)理M查詢(xún)百度叙凡,獲得結(jié)果后回調(diào)該block。

<h1>18密末、block 實(shí)現(xiàn)原理</h1>

Objective-C是對(duì)C語(yǔ)言的擴(kuò)展握爷,block的實(shí)現(xiàn)是基于指針和函數(shù)指針。
從計(jì)算語(yǔ)言的發(fā)展严里,最早的goto新啼,高級(jí)語(yǔ)言的指針,到面向?qū)ο笳Z(yǔ)言的block刹碾,從機(jī)器的思維燥撞,一步步接近人的思維,以方便開(kāi)發(fā)人員更為高效、直接的描述出現(xiàn)實(shí)的邏輯(需求)物舒。
使用實(shí)例:cocoaTouch框架下動(dòng)畫(huà)效果的Block的調(diào)用

使用typed聲明block
typedef void(^didFinishBlock) (NSObject *ob);
這就聲明了一個(gè)didFinishBlock類(lèi)型的block色洞,
然后便可用
@property (nonatomic,copy) didFinishBlock finishBlock;
聲明一個(gè)blokc對(duì)象,注意對(duì)象屬性設(shè)置為copy冠胯,接到block 參數(shù)時(shí)火诸,便會(huì)自動(dòng)復(fù)制一份。
__block是一種特殊類(lèi)型荠察,
使用該關(guān)鍵字聲明的局部變量置蜀,可以被block所改變,并且其在原函數(shù)中的值會(huì)被改變悉盆。

<h1>19盯荤、關(guān)于block</h1>

面試時(shí),面試官會(huì)先問(wèn)一些舀瓢,是否了解block廷雅,是否使用過(guò)block,這些問(wèn)題相當(dāng)于開(kāi)場(chǎng)白京髓,往往是下面一系列問(wèn)題的開(kāi)始航缀,所以一定要如實(shí)根據(jù)自己的情況回答。

1). 使用block和使用delegate完成委托模式有什么優(yōu)點(diǎn)?

首先要了解什么是委托模式堰怨,委托模式在iOS中大量應(yīng)用芥玉,其在設(shè)計(jì)模式中是適配器模式中的對(duì)象適配器,Objective-C中使用id類(lèi)型指向一切對(duì)象备图,使委托模式更為簡(jiǎn)潔灿巧。了解委托模式的細(xì)節(jié):

iOS設(shè)計(jì)模式—-委托模式

使用block實(shí)現(xiàn)委托模式,其優(yōu)點(diǎn)是回調(diào)的block代碼塊定義在委托對(duì)象函數(shù)內(nèi)部揽涮,使代碼更為緊湊;

適配對(duì)象不再需要實(shí)現(xiàn)具體某個(gè)protocol抠藕,代碼更為簡(jiǎn)潔。

2). 多線程與block

GCD與Block

使用 dispatch_async 系列方法蒋困,可以以指定的方式執(zhí)行block

GCD編程實(shí)例

dispatch_async的完整定義

void dispatch_async(

dispatch_queue_t queue,

dispatch_block_t block);

功能:在指定的隊(duì)列里提交一個(gè)異步執(zhí)行的block盾似,不阻塞當(dāng)前線程

通過(guò)queue來(lái)控制block執(zhí)行的線程。主線程執(zhí)行前文定義的 finishBlock對(duì)象

dispatch_async(dispatch_get_main_queue(),^(void){finishBlock();});

<h1>20雪标、解釋以下代碼的內(nèi)存泄漏原因</h1>

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {       
    HJTestCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TestCell" forIndexPath:indexPath];
    [cell setTouchBlock:^(HJTestCell *cell) {
        [self refreshData];
    }];       
   return cell;
}

原因:

[cell setTouchBlock:^(HJTestCell *cell) {
    [self refreshData];
}];

產(chǎn)生內(nèi)存泄露的原因是因?yàn)檠h(huán)引用

在給cell設(shè)置的TouchBlock中零院,使用了__strong修飾的self,由于Block的原理村刨,當(dāng)touchBlock從棧復(fù)制到堆中時(shí)告抄,self會(huì)一同復(fù)制到堆中,retain一次嵌牺,被touchBlock持有打洼,而touchBlock又是被cell持有的龄糊,cell又被tableView持有,tableView又被self持有拟蜻,因此形成了循環(huán)引用:self間接持有touchBlock绎签,touchBlock持有self

一旦產(chǎn)生了循環(huán)引用,由于兩個(gè)object都被強(qiáng)引用酝锅,所以retainCount始終不能為0诡必,無(wú)發(fā)釋放,產(chǎn)生內(nèi)存泄漏

解決辦法:
使用weakSelf解除touchBlock對(duì)self的強(qiáng)引用

__weak __typeof__(self) weakSelf = self;
[cell setTouchBlock:^(HJTestCell *cell) {
    [weakSelf refreshData];
}];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搔扁,一起剝皮案震驚了整個(gè)濱河市爸舒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稿蹲,老刑警劉巖扭勉,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異苛聘,居然都是意外死亡涂炎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)设哗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唱捣,“玉大人,你說(shuō)我怎么就攤上這事网梢≌痃裕” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵战虏,是天一觀的道長(zhǎng)拣宰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)烦感,這世上最難降的妖魔是什么巡社? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮手趣,結(jié)果婚禮上重贺,老公的妹妹穿的比我還像新娘。我一直安慰自己回懦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布次企。 她就那樣靜靜地躺著怯晕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缸棵。 梳的紋絲不亂的頭發(fā)上舟茶,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼吧凉。 笑死隧出,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阀捅。 我是一名探鬼主播胀瞪,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼饲鄙!你這毒婦竟也來(lái)了凄诞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤忍级,失蹤者是張志新(化名)和其女友劉穎帆谍,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體轴咱,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汛蝙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朴肺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖剑。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宇挫,靈堂內(nèi)的尸體忽然破棺而出苛吱,到底是詐尸還是另有隱情,我是刑警寧澤器瘪,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布翠储,位于F島的核電站,受9級(jí)特大地震影響橡疼,放射性物質(zhì)發(fā)生泄漏援所。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一欣除、第九天 我趴在偏房一處隱蔽的房頂上張望住拭。 院中可真熱鬧,春花似錦历帚、人聲如沸滔岳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谱煤。三九已至,卻和暖如春禽拔,著一層夾襖步出監(jiān)牢的瞬間刘离,已是汗流浹背室叉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硫惕,地道東北人茧痕。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像恼除,于是被迫代替她去往敵國(guó)和親踪旷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

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

  • Block Block底層原理實(shí)現(xiàn) 首先我們來(lái)看四個(gè)函數(shù) 造成這樣的原因是:傳值和傳址缚柳。為什么說(shuō)會(huì)有傳值和傳址埃脏,把...
    b485c88ab697閱讀 7,839評(píng)論 0 41
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛(ài)閱讀 1,990評(píng)論 0 7
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理秋忙。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場(chǎng)景彩掐。SDWebImage的原...
    LZM輪回閱讀 2,009評(píng)論 0 12
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,168評(píng)論 30 470
  • 前言 Blocks是C語(yǔ)言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,774評(píng)論 0 23