9掘宪、圖層時(shí)間

圖層時(shí)間

時(shí)間和空間最大的區(qū)別在于寇钉,時(shí)間不能被復(fù)用 -- 弗斯特梅里克

在上面兩章中,我們探討了可以用CAAnimation和它的子類實(shí)現(xiàn)的多種圖層動(dòng)畫违寿。動(dòng)畫的發(fā)生是需要持續(xù)一段時(shí)間的湃交,所以計(jì)時(shí)對(duì)整個(gè)概念來(lái)說(shuō)至關(guān)重要。在這一章中藤巢,我們來(lái)看看CAMediaTiming搞莺,看看Core Animation是如何跟蹤時(shí)間的。

CAMediaTiming協(xié)議

CAMediaTiming協(xié)議定義了在一段動(dòng)畫內(nèi)用來(lái)控制逝去時(shí)間的屬性的集合掂咒,CALayerCAAnimation都實(shí)現(xiàn)了這個(gè)協(xié)議才沧,所以時(shí)間可以被任意基于一個(gè)圖層或者一段動(dòng)畫的類控制。

持續(xù)和重復(fù)

我們?cè)诘诎苏隆帮@式動(dòng)畫”中簡(jiǎn)單提到過(guò)durationCAMediaTiming的屬性之一)绍刮,duration是一個(gè)CFTimeInterval的類型(類似于NSTimeInterval的一種雙精度浮點(diǎn)類型)温圆,對(duì)將要進(jìn)行的動(dòng)畫的一次迭代指定了時(shí)間。

這里的一次迭代是什么意思呢孩革?CAMediaTiming另外還有一個(gè)屬性叫做repeatCount岁歉,代表動(dòng)畫重復(fù)的迭代次數(shù)。如果duration是2膝蜈,repeatCount設(shè)為3.5(三個(gè)半迭代)锅移,那么完整的動(dòng)畫時(shí)長(zhǎng)將是7秒。

durationrepeatCount默認(rèn)都是0饱搏。但這不意味著動(dòng)畫時(shí)長(zhǎng)為0秒非剃,或者0次,這里的0僅僅代表了“默認(rèn)”推沸,也就是0.25秒和1次备绽,你可以用一個(gè)簡(jiǎn)單的測(cè)試來(lái)嘗試為這兩個(gè)屬性賦多個(gè)值券坞,如清單9.1,圖9.1展示了程序的結(jié)果疯坤。

清單9.1 測(cè)試durationrepeatCount

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic, weak) IBOutlet UITextField *durationField;
@property (nonatomic, weak) IBOutlet UITextField *repeatField;
@property (nonatomic, weak) IBOutlet UIButton *startButton;
@property (nonatomic, strong) CALayer *shipLayer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //add the ship
    self.shipLayer = [CALayer layer];
    self.shipLayer.frame = CGRectMake(0, 0, 128, 128);
    self.shipLayer.position = CGPointMake(150, 150);
    self.shipLayer.contents = (__bridge id)[UIImage imageNamed: @"Ship.png"].CGImage;
    [self.containerView.layer addSublayer:self.shipLayer];
}

- (void)setControlsEnabled:(BOOL)enabled
{
    for (UIControl *control in @[self.durationField, self.repeatField, self.startButton]) {
        control.enabled = enabled;
        control.alpha = enabled? 1.0f: 0.25f;
    }
}

- (IBAction)hideKeyboard
{
    [self.durationField resignFirstResponder];
    [self.repeatField resignFirstResponder];
}

- (IBAction)start
{
    CFTimeInterval duration = [self.durationField.text doubleValue];
    float repeatCount = [self.repeatField.text floatValue];
    //animate the ship rotation
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"transform.rotation";
    animation.duration = duration;
    animation.repeatCount = repeatCount;
    animation.byValue = @(M_PI * 2);
    animation.delegate = self;
    [self.shipLayer addAnimation:animation forKey:@"rotateAnimation"];
    //disable controls
    [self setControlsEnabled:NO];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    //reenable controls
    [self setControlsEnabled:YES];
}

@end
圖9.1 演示`duration`和`repeatCount`的測(cè)試程序

創(chuàng)建重復(fù)動(dòng)畫的另一種方式是使用repeatDuration屬性,它讓動(dòng)畫重復(fù)一個(gè)指定的時(shí)間深浮,而不是指定次數(shù)压怠。你甚至設(shè)置一個(gè)叫做autoreverses的屬性(BOOL類型)在每次間隔交替循環(huán)過(guò)程中自動(dòng)回放。這對(duì)于播放一段連續(xù)非循環(huán)的動(dòng)畫很有用飞苇,例如打開一扇門菌瘫,然后關(guān)上它(圖9.2)。

圖9.2 擺動(dòng)門的動(dòng)畫

對(duì)門進(jìn)行擺動(dòng)的代碼見清單9.2布卡。我們用了autoreverses來(lái)使門在打開后自動(dòng)關(guān)閉雨让,在這里我們把repeatDuration設(shè)置為INFINITY,于是動(dòng)畫無(wú)限循環(huán)播放忿等,設(shè)置repeatCountINFINITY也有同樣的效果栖忠。注意repeatCountrepeatDuration可能會(huì)相互沖突,所以你只要對(duì)其中一個(gè)指定非零值贸街。對(duì)兩個(gè)屬性都設(shè)置非0值的行為沒有被定義庵寞。

清單9.2 使用autoreverses屬性實(shí)現(xiàn)門的搖擺

@interface ViewController ()

@property (nonatomic, weak) UIView *containerView;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //add the door
    CALayer *doorLayer = [CALayer layer];
    doorLayer.frame = CGRectMake(0, 0, 128, 256);
    doorLayer.position = CGPointMake(150 - 64, 150);
    doorLayer.anchorPoint = CGPointMake(0, 0.5);
    doorLayer.contents = (__bridge id)[UIImage imageNamed: @"Door.png"].CGImage;
    [self.containerView.layer addSublayer:doorLayer];
    //apply perspective transform
    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = -1.0 / 500.0;
    self.containerView.layer.sublayerTransform = perspective;
    //apply swinging animation
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"transform.rotation.y";
    animation.toValue = @(-M_PI_2);
    animation.duration = 2.0;
    animation.repeatDuration = INFINITY;
    animation.autoreverses = YES;
    [doorLayer addAnimation:animation forKey:nil];
}

@end

相對(duì)時(shí)間

每次討論到Core Animation,時(shí)間都是相對(duì)的薛匪,每個(gè)動(dòng)畫都有它自己描述的時(shí)間捐川,可以獨(dú)立地加速,延時(shí)或者偏移逸尖。

beginTime指定了動(dòng)畫開始之前的的延遲時(shí)間古沥。這里的延遲從動(dòng)畫添加到可見圖層的那一刻開始測(cè)量,默認(rèn)是0(就是說(shuō)動(dòng)畫會(huì)立刻執(zhí)行)娇跟。

speed是一個(gè)時(shí)間的倍數(shù)岩齿,默認(rèn)1.0,減少它會(huì)減慢圖層/動(dòng)畫的時(shí)間苞俘,增加它會(huì)加快速度纯衍。如果2.0的速度,那么對(duì)于一個(gè)duration為1的動(dòng)畫苗胀,實(shí)際上在0.5秒的時(shí)候就已經(jīng)完成了襟诸。

timeOffsetbeginTime類似,但是和增加beginTime導(dǎo)致的延遲動(dòng)畫不同基协,增加timeOffset只是讓動(dòng)畫快進(jìn)到某一點(diǎn)歌亲,例如,對(duì)于一個(gè)持續(xù)1秒的動(dòng)畫來(lái)說(shuō)澜驮,設(shè)置timeOffset為0.5意味著動(dòng)畫將從一半的地方開始陷揪。

beginTime不同的是,timeOffset并不受speed的影響。所以如果你把speed設(shè)為2.0悍缠,把timeOffset設(shè)置為0.5卦绣,那么你的動(dòng)畫將從動(dòng)畫最后結(jié)束的地方開始,因?yàn)?秒的動(dòng)畫實(shí)際上被縮短到了0.5秒飞蚓。然而即使使用了timeOffset讓動(dòng)畫從結(jié)束的地方開始滤港,它仍然播放了一個(gè)完整的時(shí)長(zhǎng),這個(gè)動(dòng)畫僅僅是循環(huán)了一圈趴拧,然后從頭開始播放溅漾。

可以用清單9.3的測(cè)試程序驗(yàn)證一下,設(shè)置speedtimeOffset滑塊到隨意的值著榴,然后點(diǎn)擊播放來(lái)觀察效果(見圖9.3)

清單9.3 測(cè)試timeOffsetspeed屬性

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic, weak) IBOutlet UILabel *speedLabel;
@property (nonatomic, weak) IBOutlet UILabel *timeOffsetLabel;
@property (nonatomic, weak) IBOutlet UISlider *speedSlider;
@property (nonatomic, weak) IBOutlet UISlider *timeOffsetSlider;
@property (nonatomic, strong) UIBezierPath *bezierPath;
@property (nonatomic, strong) CALayer *shipLayer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //create a path
    self.bezierPath = [[UIBezierPath alloc] init];
    [self.bezierPath moveToPoint:CGPointMake(0, 150)];
    [self.bezierPath addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(75, 0) controlPoint2:CGPointMake(225, 300)];
    //draw the path using a CAShapeLayer
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.path = self.bezierPath.CGPath;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.strokeColor = [UIColor redColor].CGColor;
    pathLayer.lineWidth = 3.0f;
    [self.containerView.layer addSublayer:pathLayer];
    //add the ship
    self.shipLayer = [CALayer layer];
    self.shipLayer.frame = CGRectMake(0, 0, 64, 64);
    self.shipLayer.position = CGPointMake(0, 150);
    self.shipLayer.contents = (__bridge id)[UIImage imageNamed: @"Ship.png"].CGImage;
    [self.containerView.layer addSublayer:self.shipLayer];
    //set initial values
    [self updateSliders];
}

- (IBAction)updateSliders
{
    CFTimeInterval timeOffset = self.timeOffsetSlider.value;
    self.timeOffsetLabel.text = [NSString stringWithFormat:@"%0.2f", timeOffset];
    float speed = self.speedSlider.value;
    self.speedLabel.text = [NSString stringWithFormat:@"%0.2f", speed];
}

- (IBAction)play
{
    //create the keyframe animation
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    animation.timeOffset = self.timeOffsetSlider.value;
    animation.speed = self.speedSlider.value;
    animation.duration = 1.0;
    animation.path = self.bezierPath.CGPath;
    animation.rotationMode = kCAAnimationRotateAuto;
    animation.removedOnCompletion = NO;
    [self.shipLayer addAnimation:animation forKey:@"slide"];
}

@end
圖9.3 測(cè)試時(shí)間偏移和速度的簡(jiǎn)單的應(yīng)用程序

fillMode

對(duì)于beginTime非0的一段動(dòng)畫來(lái)說(shuō)添履,會(huì)出現(xiàn)一個(gè)當(dāng)動(dòng)畫添加到圖層上但什么也沒發(fā)生的狀態(tài)。類似的脑又,removeOnCompletion被設(shè)置為NO的動(dòng)畫將會(huì)在動(dòng)畫結(jié)束的時(shí)候仍然保持之前的狀態(tài)暮胧。這就產(chǎn)生了一個(gè)問題,當(dāng)動(dòng)畫開始之前和動(dòng)畫結(jié)束之后问麸,被設(shè)置動(dòng)畫的屬性將會(huì)是什么值呢叔壤?

一種可能是屬性和動(dòng)畫沒被添加之前保持一致,也就是在模型圖層定義的值(見第七章“隱式動(dòng)畫”口叙,模型圖層和呈現(xiàn)圖層的解釋)炼绘。

另一種可能是保持動(dòng)畫開始之前那一幀,或者動(dòng)畫結(jié)束之后的那一幀妄田。這就是所謂的填充俺亮,因?yàn)閯?dòng)畫開始和結(jié)束的值用來(lái)填充開始之前和結(jié)束之后的時(shí)間。

這種行為就交給開發(fā)者了疟呐,它可以被CAMediaTimingfillMode來(lái)控制脚曾。fillMode是一個(gè)NSString類型,可以接受如下四種常量:

kCAFillModeForwards
kCAFillModeBackwards
kCAFillModeBoth
kCAFillModeRemoved

默認(rèn)是kCAFillModeRemoved启具,當(dāng)動(dòng)畫不再播放的時(shí)候就顯示圖層模型指定的值本讥。剩下的三種類型分別為向前,向后或者既向前又向后去填充動(dòng)畫狀態(tài)鲁冯,使得動(dòng)畫在開始前或者結(jié)束后仍然保持開始和結(jié)束那一刻的值拷沸。

這就對(duì)避免在動(dòng)畫結(jié)束的時(shí)候急速返回提供另一種方案(見第八章)。但是記住了薯演,當(dāng)用它來(lái)解決這個(gè)問題的時(shí)候撞芍,需要把removeOnCompletion設(shè)置為NO,另外需要給動(dòng)畫添加一個(gè)非空的鍵跨扮,于是可以在不需要?jiǎng)赢嫷臅r(shí)候把它從圖層上移除序无。

層級(jí)關(guān)系時(shí)間

在第三章“圖層幾何學(xué)”中验毡,你已經(jīng)了解到每個(gè)圖層是如何相對(duì)在圖層樹中的父圖層定義它的坐標(biāo)系的。動(dòng)畫時(shí)間和它類似帝嗡,每個(gè)動(dòng)畫和圖層在時(shí)間上都有它自己的層級(jí)概念晶通,相對(duì)于它的父親來(lái)測(cè)量。對(duì)圖層調(diào)整時(shí)間將會(huì)影響到它本身和子圖層的動(dòng)畫哟玷,但不會(huì)影響到父圖層狮辽。另一個(gè)相似點(diǎn)是所有的動(dòng)畫都被按照層級(jí)組合(使用CAAnimationGroup實(shí)例)。

對(duì)CALayer或者CAAnimationGroup調(diào)整durationrepeatCount/repeatDuration屬性并不會(huì)影響到子動(dòng)畫碗降。但是beginTime隘竭,timeOffsetspeed屬性將會(huì)影響到子動(dòng)畫塘秦。然而在層級(jí)關(guān)系中讼渊,beginTime指定了父圖層開始動(dòng)畫(或者組合關(guān)系中的父動(dòng)畫)和對(duì)象將要開始自己動(dòng)畫之間的偏移。類似的尊剔,調(diào)整CALayerCAGroupAnimationspeed屬性將會(huì)對(duì)動(dòng)畫以及子動(dòng)畫速度應(yīng)用一個(gè)縮放的因子爪幻。

全局時(shí)間和本地時(shí)間

CoreAnimation有一個(gè)全局時(shí)間的概念,也就是所謂的馬赫時(shí)間(“馬赫”實(shí)際上是iOS和Mac OS系統(tǒng)內(nèi)核的命名)须误。馬赫時(shí)間在設(shè)備上所有進(jìn)程都是全局的--但是在不同設(shè)備上并不是全局的--不過(guò)這已經(jīng)足夠?qū)?dòng)畫的參考點(diǎn)提供便利了挨稿,你可以使用CACurrentMediaTime函數(shù)來(lái)訪問馬赫時(shí)間:

CFTimeInterval time = CACurrentMediaTime();

這個(gè)函數(shù)返回的值其實(shí)無(wú)關(guān)緊要(它返回了設(shè)備自從上次啟動(dòng)后的秒數(shù),并不是你所關(guān)心的)京痢,它真實(shí)的作用在于對(duì)動(dòng)畫的時(shí)間測(cè)量提供了一個(gè)相對(duì)值奶甘。注意當(dāng)設(shè)備休眠的時(shí)候馬赫時(shí)間會(huì)暫停,也就是所有的CAAnimations(基于馬赫時(shí)間)同樣也會(huì)暫停祭椰。

因此馬赫時(shí)間對(duì)長(zhǎng)時(shí)間測(cè)量并不有用臭家。比如用CACurrentMediaTime去更新一個(gè)實(shí)時(shí)鬧鐘并不明智。(可以用[NSDate date]代替方淤,就像第三章例子所示)钉赁。

每個(gè)CALayerCAAnimation實(shí)例都有自己本地時(shí)間的概念,是根據(jù)父圖層/動(dòng)畫層級(jí)關(guān)系中的beginTime携茂,timeOffsetspeed屬性計(jì)算你踩。就和轉(zhuǎn)換不同圖層之間坐標(biāo)關(guān)系一樣,CALayer同樣也提供了方法來(lái)轉(zhuǎn)換不同圖層之間的本地時(shí)間讳苦。如下:

- (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l;
- (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;

當(dāng)用來(lái)同步不同圖層之間有不同的speed带膜,timeOffsetbeginTime的動(dòng)畫,這些方法會(huì)很有用鸳谜。

暫停钱慢,倒回和快進(jìn)

設(shè)置動(dòng)畫的speed屬性為0可以暫停動(dòng)畫,但在動(dòng)畫被添加到圖層之后不太可能再修改它了卿堂,所以不能對(duì)正在進(jìn)行的動(dòng)畫使用這個(gè)屬性束莫。給圖層添加一個(gè)CAAnimation實(shí)際上是給動(dòng)畫對(duì)象做了一個(gè)不可改變的拷貝懒棉,所以對(duì)原始動(dòng)畫對(duì)象屬性的改變對(duì)真實(shí)的動(dòng)畫并沒有作用。相反览绿,直接用-animationForKey:來(lái)檢索圖層正在進(jìn)行的動(dòng)畫可以返回正確的動(dòng)畫對(duì)象策严,但是修改它的屬性將會(huì)拋出異常。

如果移除圖層正在進(jìn)行的動(dòng)畫饿敲,圖層將會(huì)急速返回動(dòng)畫之前的狀態(tài)妻导。但如果在動(dòng)畫移除之前拷貝呈現(xiàn)圖層到模型圖層,動(dòng)畫將會(huì)看起來(lái)暫停在那里怀各。但是不好的地方在于之后就不能再恢復(fù)動(dòng)畫了倔韭。

一個(gè)簡(jiǎn)單的方法是可以利用CAMediaTiming來(lái)暫停圖層本身。如果把圖層的speed設(shè)置成0瓢对,它會(huì)暫停任何添加到圖層上的動(dòng)畫寿酌。類似的,設(shè)置speed大于1.0將會(huì)快進(jìn)硕蛹,設(shè)置成一個(gè)負(fù)值將會(huì)倒回動(dòng)畫醇疼。

通過(guò)增加主窗口圖層的speed,可以暫停整個(gè)應(yīng)用程序的動(dòng)畫法焰。這對(duì)UI自動(dòng)化提供了好處秧荆,我們可以加速所有的視圖動(dòng)畫來(lái)進(jìn)行自動(dòng)化測(cè)試(注意對(duì)于在主窗口之外的視圖并不會(huì)被影響,比如UIAlertview)埃仪∫冶簦可以在app delegate設(shè)置如下進(jìn)行驗(yàn)證:

self.window.layer.speed = 100;

你也可以通過(guò)這種方式來(lái)減速,但其實(shí)也可以在模擬器通過(guò)切換慢速動(dòng)畫來(lái)實(shí)現(xiàn)卵蛉。

手動(dòng)動(dòng)畫

timeOffset一個(gè)很有用的功能在于它可以讓你手動(dòng)控制動(dòng)畫進(jìn)程颁股,通過(guò)設(shè)置speed為0,可以禁用動(dòng)畫的自動(dòng)播放毙玻,然后來(lái)使用timeOffset來(lái)來(lái)回顯示動(dòng)畫序列豌蟋。這可以使得運(yùn)用手勢(shì)來(lái)手動(dòng)控制動(dòng)畫變得很簡(jiǎn)單。

舉個(gè)簡(jiǎn)單的例子:還是之前關(guān)門的動(dòng)畫桑滩,修改代碼來(lái)用手勢(shì)控制動(dòng)畫梧疲。我們給視圖添加一個(gè)UIPanGestureRecognizer,然后用timeOffset左右搖晃运准。

因?yàn)樵趧?dòng)畫添加到圖層之后不能再做修改了幌氮,我們來(lái)通過(guò)調(diào)整layertimeOffset達(dá)到同樣的效果(清單9.4)。

清單9.4 通過(guò)觸摸手勢(shì)手動(dòng)控制動(dòng)畫

@interface ViewController ()

@property (nonatomic, weak) UIView *containerView;
@property (nonatomic, strong) CALayer *doorLayer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //add the door
    self.doorLayer = [CALayer layer];
    self.doorLayer.frame = CGRectMake(0, 0, 128, 256);
    self.doorLayer.position = CGPointMake(150 - 64, 150);
    self.doorLayer.anchorPoint = CGPointMake(0, 0.5);
    self.doorLayer.contents = (__bridge id)[UIImage imageNamed:@"Door.png"].CGImage;
    [self.containerView.layer addSublayer:self.doorLayer];
    //apply perspective transform
    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = -1.0 / 500.0;
    self.containerView.layer.sublayerTransform = perspective;
    //add pan gesture recognizer to handle swipes
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] init];
    [pan addTarget:self action:@selector(pan:)];
    [self.view addGestureRecognizer:pan];
    //pause all layer animations
    self.doorLayer.speed = 0.0;
    //apply swinging animation (which won't play because layer is paused)
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"transform.rotation.y";
    animation.toValue = @(-M_PI_2);
    animation.duration = 1.0;
    [self.doorLayer addAnimation:animation forKey:nil];
}

- (void)pan:(UIPanGestureRecognizer *)pan
{
    //get horizontal component of pan gesture
    CGFloat x = [pan translationInView:self.view].x;
    //convert from points to animation duration //using a reasonable scale factor
    x /= 200.0f;
    //update timeOffset and clamp result
    CFTimeInterval timeOffset = self.doorLayer.timeOffset;
    timeOffset = MIN(0.999, MAX(0.0, timeOffset - x));
    self.doorLayer.timeOffset = timeOffset;
    //reset pan gesture
    [pan setTranslation:CGPointZero inView:self.view];
}

@end

這其實(shí)是個(gè)小詭計(jì)胁澳,也許相對(duì)于設(shè)置個(gè)動(dòng)畫然后每次顯示一幀而言该互,用移動(dòng)手勢(shì)來(lái)直接設(shè)置門的transform會(huì)更簡(jiǎn)單。

在這個(gè)例子中的確是這樣韭畸,但是對(duì)于比如說(shuō)關(guān)鍵這這樣更加復(fù)雜的情況宇智,或者有多個(gè)圖層的動(dòng)畫組蔓搞,相對(duì)于實(shí)時(shí)計(jì)算每個(gè)圖層的屬性而言,這就顯得方便的多了随橘。

總結(jié)

在這一章喂分,我們了解了CAMediaTiming協(xié)議,以及Core Animation用來(lái)操作時(shí)間控制動(dòng)畫的機(jī)制机蔗。在下一章蒲祈,我們將要接觸緩沖,另一個(gè)用來(lái)使動(dòng)畫更加真實(shí)的操作時(shí)間的技術(shù)萝嘁。

文章摘錄自:https://github.com/AttackOnDobby/iOS-Core-Animation-Advanced-Techniques

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梆掸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子牙言,更是在濱河造成了極大的恐慌酸钦,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嬉挡,死亡現(xiàn)場(chǎng)離奇詭異钝鸽,居然都是意外死亡汇恤,警方通過(guò)查閱死者的電腦和手機(jī)庞钢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)因谎,“玉大人基括,你說(shuō)我怎么就攤上這事〔撇恚” “怎么了风皿?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)匠璧。 經(jīng)常有香客問我桐款,道長(zhǎng),這世上最難降的妖魔是什么夷恍? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任魔眨,我火速辦了婚禮,結(jié)果婚禮上酿雪,老公的妹妹穿的比我還像新娘遏暴。我一直安慰自己,他們只是感情好指黎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布朋凉。 她就那樣靜靜地躺著,像睡著了一般醋安。 火紅的嫁衣襯著肌膚如雪杂彭。 梳的紋絲不亂的頭發(fā)上墓毒,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音亲怠,去河邊找鬼蚁鳖。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赁炎,可吹牛的內(nèi)容都是我干的醉箕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼徙垫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼讥裤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起姻报,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤己英,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吴旋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體损肛,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年荣瑟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了治拿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笆焰,死狀恐怖劫谅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嚷掠,我是刑警寧澤捏检,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站不皆,受9級(jí)特大地震影響贯城,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霹娄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一能犯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧项棠,春花似錦悲雳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至透典,卻和暖如春晴楔,著一層夾襖步出監(jiān)牢的瞬間顿苇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工税弃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纪岁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓则果,卻偏偏與公主長(zhǎng)得像幔翰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子西壮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • 本文轉(zhuǎn)載自:http://www.cocoachina.com/ios/20150105/10829.html 為...
    idiot_lin閱讀 247評(píng)論 0 1
  • 時(shí)間和空間最大的區(qū)別在于遗增,時(shí)間不能被復(fù)用 -- 弗斯特梅里克 在上面兩章中,我們探討了可以用CAAnimation...
    雪_晟閱讀 123評(píng)論 0 0
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果款青,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜做修,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,489評(píng)論 6 30
  • 逼著自己去回憶 逼著自己去忘記 提筆 留下幾行字
    荔枝椏閱讀 77評(píng)論 0 0
  • 5月3日:《執(zhí)行》第九章 把戰(zhàn)略計(jì)劃書執(zhí)行為一個(gè)具體的可傳承的結(jié)果抡草,需要三個(gè)階段饰及,共12環(huán)節(jié)。 1)做前階段: 期...
    易查理閱讀 467評(píng)論 0 0