學(xué)習(xí)RxSwift & MVVM-C(一)

函數(shù)響應(yīng)式編程FRP

之前學(xué)習(xí)過(guò)Objective-C下的FRP第三方開(kāi)源框架ReactiveCocoa,部分學(xué)習(xí)筆記:
https://blog.csdn.net/wf96390/article/details/50933421
它可以在MVVM架構(gòu)模式中充當(dāng)著View(視圖)層與ViewModel(視圖模型)層之間的Binder(綁定者)角色锄俄,實(shí)現(xiàn)兩個(gè)層之間的同步更新察蹲。在ReactiveCocoa的世界中坎炼,數(shù)據(jù)與屬性的改變扳炬、視圖的操作反饋、方法的調(diào)用等都可以被監(jiān)聽(tīng)并抽象轉(zhuǎn)換成事件流序芦,封裝在Signal(信號(hào))中愧沟,我們通過(guò)對(duì)Signal的Subscribe(訂閱)就能獲取到其中的事件流蔬咬,并進(jìn)行相應(yīng)的操作鲤遥。

函數(shù)式編程 Functional programming

總結(jié)一下函數(shù)式編程具有以下幾個(gè)特點(diǎn):

  • 函數(shù)是“第一等公民”
  • 閉包和高階函數(shù)
  • 只用“表達(dá)式”,不用“語(yǔ)句”林艘,不改變狀態(tài)盖奈,沒(méi)有副作用
  • 柯里化

Haskell是一種標(biāo)準(zhǔn)化的、通用純函數(shù)式編程語(yǔ)言北启,有非限定性語(yǔ)義和強(qiáng)靜態(tài)類型卜朗。

響應(yīng)式編程

var b = 1
let c = 2
let a = b  + c  // a = 3

// 改變 b 的值,a的值會(huì)變嗎咕村?
b = 3
print(a)

在命令式編程環(huán)境中场钉, a = b + c 表示將表達(dá)式的結(jié)果賦給 a,而之后改變 b 或 c的值不會(huì)影響 a懈涛。
但在響應(yīng)式編程中逛万,a的值會(huì)隨著 b或 c的更新而更新。

RxSwift

RxSwift是Reactive下的一個(gè)分支批钠,Reactive涵蓋了很多語(yǔ)言宇植。

RxSwift為ReactiveX(Reactive Extensions)旗下的Swift語(yǔ)言庫(kù),提供了Swift平臺(tái)上進(jìn)行響應(yīng)式編程的解決方案埋心。Rx的重要角色為Observable(被觀察者)和Observer(觀察者)指郁,Observable類似于ReactiveCocoa中的Signal,里面裝有事件流拷呆,供Observer訂閱闲坎。事件流在Rx中與ReactiveCocoa一樣具有三類:Next、Error茬斧、Completed腰懂,代表著繼續(xù)事件、錯(cuò)誤事件项秉、完成事件绣溜。我們?cè)谑褂肦xSwift進(jìn)行iOS開(kāi)發(fā)時(shí),通常會(huì)引入另外一個(gè)庫(kù):RxCocoa娄蔼,這個(gè)庫(kù)將UIKit以及Foundation框架中許多成員怖喻,如視圖(View)、控制事件(Control Event)岁诉、鍵值觀察(KVO)罢防、通知(Notification)等等進(jìn)行與RxSwift接入的擴(kuò)展,將Rx與iOS API無(wú)縫連接唉侄。

Observable 和 Observer

Observable指的是可被觀察者或者事件源。Observable是一種像信號(hào)一樣的序列野建,可以理解為一串?dāng)?shù)組属划,但是需要有人監(jiān)聽(tīng)這些信號(hào)恬叹。ObservableType協(xié)議中定義的subscribe函數(shù)就是一種簡(jiǎn)便的訂閱信號(hào)的一種方法。這里的subscribe函數(shù)就是把消息發(fā)給觀察者同眯。

實(shí)現(xiàn)了 ObservableType 協(xié)議, ObservableType 協(xié)議中定義了很多方法绽昼。

public class Observable<Element> : ObservableType {
    public func subscribe<O>(_ observer: O) -> Disposable where Element == O.E, O : ObserverType

    public func asObservable() -> RxSwift.Observable<RxSwift.Observable<Element>.E>
}

Observer : 觀察者,觀察者需要訂閱Observable须蜗,才能受到其發(fā)出的事件

subscribe :用于訂閱sequence發(fā)出的事件硅确,相當(dāng)于Swift序列中的遍歷操作(makeIterator)

subscribe(_:)方法接受事件參數(shù),下面這個(gè)例子接受元素參數(shù)
someObservable.subscribe(
    onNext: { print("Element:", $0) },
    onError: { print("Error:", $0) },
    onCompleted: { print("Completed") },
    onDisposed: { print("Disposed") }
)

Dispose

在使用subscribe訂閱一個(gè)可觀察序列時(shí)明肮,會(huì)返回一個(gè)Disposable類型的對(duì)象菱农。這里的Disposable是一個(gè)協(xié)議,只定義了一個(gè)方法:

public protocol Disposable {
    /// Dispose resource.
    func dispose()
}

DisposeBag : 類似于 iOS 中的 ARC柿估,會(huì)在適當(dāng)?shù)臅r(shí)候銷毀觀察者循未,自動(dòng)去釋放資源。需要調(diào)用 disposed 方法秫舌,加入到 disposed 中的妖。如果未添加 Xcode 會(huì)提示報(bào)錯(cuò)。

let disposeBag = DisposeBag()

extension Disposable {

    /// Adds `self` to `bag`
    ///
    /// - parameter bag: `DisposeBag` to add `self` to.
    public func disposed(by bag: RxSwift.DisposeBag)
}

如果需要手動(dòng)銷毀觀察者直接調(diào)用dispose()方法

Observable.empty().subscribe { (str: Event) in 
    print(“empty:”, str) 
}.dispose()

常見(jiàn)用法

Observable 類似 swift 中的序列足陨,可以用數(shù)據(jù)流圖表示
https://rxmarbles.com/

創(chuàng)建Observable

  • never

構(gòu)建一個(gè)從不終止和發(fā)出任何事件的隊(duì)列

Observable<String>.never().subscribe { _ in
   print("This will never be printed")
}
.disposed(by: disposeBag)
  • empty

構(gòu)建一個(gè)空的Observable隊(duì)列嫂粟,只發(fā)出完成事件

 Observable<Int>.empty()
     .subscribe { event in
         print(event)
     }
     .disposed(by: disposeBag)
  • just

構(gòu)建一個(gè)只有一個(gè)元素的Observable隊(duì)列

Observable.just("123")
   .subscribe { event in
       print(event)
    }
    .disposed(by: disposeBag)
  • of

構(gòu)建一個(gè)擁有固定數(shù)量元素的Observable序列

Observable.of("A", "B", "C", "D")
    .subscribe(onNext: { element in
        print(element)
    })
    .disposed(by: disposeBag)
  • from

從序列中創(chuàng)建可觀察到的序列,如數(shù)組墨缘、字典或集合星虹。

Observable.from(["??", "??", "??", "??"])
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
  • create

構(gòu)建一個(gè)自定義的可觀察序列

  let myJust = { (element: String) -> Observable<String> in
      return Observable.create { observer in
          observer.on(.next(element))
          observer.on(.completed)
          return Disposables.create()
      }
  }
 myJust("??")
     .subscribe { print($0) }
     .disposed(by: disposeBag)
  • range

創(chuàng)建一個(gè)可觀察序列,該序列釋放一系列連續(xù)整數(shù)飒房,然后終止

 Observable.range(start: 1, count: 10)
    .subscribe { print($0) }
    .disposed(by: disposeBag)
  • repeatElement

創(chuàng)建一個(gè)可觀察到的序列搁凸,它無(wú)限地釋放給定的元素

Observable.repeatElement("123")
     .take(3)
     .subscribe(onNext: { print($0) })
     .disposed(by: disposeBag)
  • generate

創(chuàng)建一個(gè)可觀察的序列,只要所提供的條件求值為true狠毯,就生成值护糖。

 Observable.generate(
        initialState: 0,
        condition: { $0 < 3 },
        iterate: { $0 + 1 }
    )
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
  • error

創(chuàng)建一個(gè)沒(méi)有任何元素的可觀察序列,并立即以錯(cuò)誤結(jié)束嚼松。

 Observable<Int>.error(TestError.test)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

創(chuàng)建Subject

Subjet 類似于ReactiveCocoa中的熱信號(hào)嫡良,可以主動(dòng)發(fā)送信號(hào),也可以被監(jiān)聽(tīng)献酗,一個(gè)Subject既可以充當(dāng)Obserable也可以充當(dāng)Observer寝受,即它可以發(fā)出事件,也可以監(jiān)聽(tīng)事件罕偎。
在被訂閱以后很澄,訂閱者可以監(jiān)聽(tīng)到訂閱之后發(fā)生的事件,像收音機(jī)發(fā)送廣播一樣,打開(kāi)收音機(jī)以后可以聽(tīng)到當(dāng)前時(shí)間以及之后的廣播甩苛,之前未收聽(tīng)到能否接收的根據(jù)Subject類型判斷蹂楣。
幾種 Subject 都是 RxSwift.Observable<Element> 的子類。

  • PublishSubject

采用PublishSubject訂閱事件的時(shí)候讯蒲,只能接收到訂閱他之后發(fā)生的事件痊土,完全和收音機(jī)聽(tīng)廣播一樣。

let publicSubject = PublishSubject<String>()
publicSubject.onNext("A")
publicSubject.onNext("B")
publicSubject.subscribe(onNext: {print("publicSubject:",$0)}).addDisposableTo(bag)
publicSubject.onNext("C")
publicSubject.onNext("D")

/**
 publicSubject: C
 publicSubject: D
 **/
  • ReplaySubject

可以接收到訂閱他之后以及之前發(fā)生的事件, 對(duì)于要接受幾個(gè)以前的事件取決于bufferSize設(shè)置的大小墨林。

let replaySubject = ReplaySubject<String>.create(bufferSize: 2)
// 如果需要接受全部的事件赁酝,則可以使用
// let replaySubject = ReplaySubject<String>.createUnbounded()

replaySubject.onNext("A")
replaySubject.onNext("B")
replaySubject.onNext("C")
replaySubject.onNext("D")
replaySubject.subscribe(onNext: {print("replaySubject:",$0)}).addDisposableTo(bag)
replaySubject.onNext("E")
replaySubject.onNext("F")
replaySubject.onNext("G")
/**
 replaySubject: C
 replaySubject: D
 replaySubject: E
 replaySubject: F
 replaySubject: G
 **/
  • BehaviorSubject

采用BehaviorSubject訂閱事件,會(huì)接收到訂閱之前的最后一個(gè)事件以及訂閱之后所有事件旭等。如果在 BehaviorSubject 創(chuàng)建后馬上監(jiān)聽(tīng)酌呆,會(huì)接收到初始值和訂閱之后的事件。

let behavior = BehaviorSubject(value: "behavior")
behavior.onNext("A")
behavior.onNext("B")
behavior.subscribe(onNext: {print("behavior:",$0)}).addDisposableTo(bag)
behavior.onNext("C")
behavior.onNext("D")

/**
 behavior: B
 behavior: C
 behavior: D
 **/
  • Variable

Variable 是對(duì) BehaviorSubject 的一個(gè)包裝辆雾。BehaviorSubject 不會(huì)因?yàn)殄e(cuò)誤而終止, 但是 variable 會(huì)被釋放肪笋。
Variable當(dāng)成Obserable, 讓訂閱者進(jìn)行訂閱時(shí), 需要asObserable轉(zhuǎn)成Obserable;

Variable發(fā)出事件, 直接修改對(duì)象的value即可;

當(dāng)事件結(jié)束時(shí),Variable會(huì)自動(dòng)發(fā)出completed事件

This concept will be deprecated from RxSwift but offical migration path hasn't been decided yet.
https://github.com/ReactiveX/RxSwift/issues/1501

Current recommended replacement for this API is RxCocoa.BehaviorRelay because:

  • Variable isn't a standard cross platform concept, hence it's out of place in RxSwift target.
  • It doesn't have a counterpart for handling events (PublishRelay). It models state only.
  • It doesn't have a consistent naming with *Relay or other Rx concepts.
  • It has an inconsistent memory management model compared to other parts of RxSwift (completes on deinit).
let variable = Variable("variable")

variable.value = "A"
variable.value = "B"
variable.asObservable().subscribe { (event:Event<String>) in
    print("variable:",event)
    }.addDisposableTo(bag)
variable.value = "C"
variable.value = "D"

/**
 variable: next(B)
 variable: next(C)
 variable: next(D)
 variable: completed
 **/

組合操作

可以將多個(gè)Observables組合成單個(gè)的Observable

  • startWith

在Observable源發(fā)出元素前度迂,發(fā)出特定的元素

Observable.of("2", "3")
    .startWith("1??")
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
  • merge

將源可觀察序列的元素組合成一個(gè)新的可觀察序列

let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
    
Observable.of(subject1, subject2)
    .merge()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
    
subject1.onNext("???")
subject1.onNext("???")
subject2.onNext("①")
subject2.onNext("②")
subject1.onNext("??")
subject2.onNext("③")
  • zip

將可觀察序列合并成一個(gè)新的可觀察序列

let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
    
Observable.zip(stringSubject, intSubject) { stringElement, intElement in
    "\(stringElement) \(intElement)"
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
    
stringSubject.onNext("???")
stringSubject.onNext("???")
    
intSubject.onNext(1)
intSubject.onNext(2)

stringSubject.onNext("??")
intSubject.onNext(3)
  • combineLatest

將可觀察隊(duì)列合并成單個(gè)新的可觀察隊(duì)列藤乙,當(dāng)多個(gè)源至少有一個(gè)的時(shí)候發(fā)出信號(hào)

let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()

Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
        "\(stringElement) \(intElement)"
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

stringSubject.onNext("???")

stringSubject.onNext("???")
intSubject.onNext(1)

intSubject.onNext(2)

stringSubject.onNext("??")

當(dāng)然可以將數(shù)組作為參數(shù)

let stringObservable = Observable.just("??")
let fruitObservable = Observable.from(["??", "??", "??"])
let animalObservable = Observable.of("??", "??", "??", "??")

Observable.combineLatest([stringObservable, fruitObservable, animalObservable]) {
        "\($0[0]) \($0[1]) \($0[2])"
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

如果你采用zip組合,那必須兩個(gè)label都有值改變才會(huì)觸發(fā)惭墓,如果使用combineLatest坛梁,則其中一個(gè)改變就會(huì)出發(fā)。

轉(zhuǎn)換操作

轉(zhuǎn)換可觀察隊(duì)列發(fā)出的Next事件里元素的操作

  • map

將轉(zhuǎn)換閉包應(yīng)用于可觀察序列發(fā)出的元素腊凶,并返回已轉(zhuǎn)換元素的一個(gè)新的可觀察序列划咐。

let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
    .map { $0 * $0 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
  • flatMap

將Observable隊(duì)列發(fā)出的元素轉(zhuǎn)換成一個(gè)新的可觀察隊(duì)列,并將兩者的輸出組合成一個(gè)新的可觀察隊(duì)列钧萍,意思就是說(shuō)會(huì)監(jiān)聽(tīng)原隊(duì)列褐缠,也會(huì)監(jiān)聽(tīng)你閉包中轉(zhuǎn)換過(guò)的隊(duì)列。

struct Player {
    var score: Variable<Int>
}

let ???? = Player(score: Variable(80))
let ???? = Player(score: Variable(90))

let player = Variable(????)

player.asObservable()
    .flatMap { $0.score.asObservable() } // Change flatMap to flatMapLatest and observe change in printed output
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

????.score.value = 85  // 會(huì)有響應(yīng)

player.value = ????    // 這邊也會(huì)有響應(yīng)  監(jiān)聽(tīng)了兩個(gè)組合隊(duì)列

????.score.value = 95 // Will be printed when using flatMap, but will not be printed when using flatMapLatest

????.score.value = 100
  • scan

以初始值開(kāi)始风瘦,然后將一個(gè)累加器閉包應(yīng)用于可觀察序列所發(fā)射的每個(gè)元素队魏,并將每個(gè)中間結(jié)果作為一個(gè)元素可觀察序列返回⊥蛏Γ看例子

Observable.of(10, 100, 1000)
    .scan(1) { aggregateValue, newValue in    // aggregateValue 之前返回的值
        aggregateValue + newValue
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)    //  11,111,1111

過(guò)濾操作

  • filter

類似于 swift 語(yǔ)法中的filter胡桨,篩選出符合條件的信號(hào)

Observable.of(
    "??", "??", "??",
    "??", "??", "??",
    "??", "??", "??")
    .filter {
        $0 == "??"
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
  • distinctUntilChanged
    直到信號(hào)變化時(shí),才發(fā)出信號(hào)瞬雹,比如使用 textfield 只有內(nèi)容變化時(shí)才發(fā)出信號(hào)
Observable.of("??", "??", "??", "??", "??", "??", "??")
    .distinctUntilChanged()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)    //??????????
  • elementAt
    獲取序列中的第某個(gè)信號(hào)
Observable.of("??", "??", "??", "??", "??", "??")
    .elementAt(3)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)   //   ??
  • single

序列發(fā)出的第一個(gè)元素(或滿足條件的第一個(gè)元素)昧谊。如果序列中有多個(gè)滿足條件的或者不存在滿足條件的,則拋出一個(gè)錯(cuò)誤酗捌。

Observable.of("??", "??", "??", "??", "??", "??")
    .single()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

增加判斷條件

Observable.of("??", "??", "??", "??", "??", "??")
    .single { $0 == "??" }
    .subscribe { print($0) }
    .disposed(by: disposeBag)   //  next(??)   completed

Observable.of("??", "??", "??", "??", "??", "??")
    .single { $0 == "??" }
    .subscribe { print($0) }
    .disposed(by: disposeBag)     // next(??) error(Sequence contains more than one element.)

Observable.of("??", "??", "??", "??", "??", "??")
    .single { $0 == "??" }
    .subscribe { print($0) }
    .disposed(by: disposeBag)  //  error(Sequence doesn't contain any elements.)
  • take

從序列的開(kāi)頭獲取指定數(shù)量的信號(hào)

Observable.of("??", "??", "??", "??", "??", "??")
    .take(3)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)  //     ??????
  • takeLast

從序列的結(jié)尾獲取指定數(shù)量的元素呢诬。

Observable.of("??", "??", "??", "??", "??", "??")
    .takeLast(3)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)  //   ??????
  • takeWhile

在指定的條件滿足時(shí)涌哲,則從可觀察序列的開(kāi)頭發(fā)出元素。

Observable.of(1, 2, 3, 4, 5, 6)
    .takeWhile { $0 < 4 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)  // 1 2 3
  • takeUntil

從源序列中獲取元素馅巷,直到引用可觀察序列發(fā)出元素結(jié)束

let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()

sourceSequence
    .takeUntil(referenceSequence)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

sourceSequence.onNext("??")
sourceSequence.onNext("??")
sourceSequence.onNext("??")

referenceSequence.onNext("??")

sourceSequence.onNext("??")
sourceSequence.onNext("??")
sourceSequence.onNext("??")   // next(??)  next(??)  next(??)  completed
  • skip

從序列的開(kāi)頭跳過(guò)指定數(shù)量的元素膛虫。

Observable.of("??", "??", "??", "??", "??", "??")
    .skip(2)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)  // ????????
  • skipWhile

從序列的開(kāi)頭跳過(guò)滿足條件的元素。

Observable.of(1, 2, 3, 4, 5, 6)
    .skipWhile { $0 < 4 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)   // 4 5 6
  • skipUntil

從源序列中跳過(guò)元素钓猬,直到引用可觀察序列發(fā)出元素。

let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()

sourceSequence
    .skipUntil(referenceSequence)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

sourceSequence.onNext("??")
sourceSequence.onNext("??")
sourceSequence.onNext("??")

referenceSequence.onNext("??")

sourceSequence.onNext("??")
sourceSequence.onNext("??")
sourceSequence.onNext("??")  // ??????

MVVM-C

參見(jiàn)下一篇文章

http://www.reibang.com/p/d1386dc7617d

CSDN博客地址:
https://blog.csdn.net/wf96390/article/details/88086808

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撩独,一起剝皮案震驚了整個(gè)濱河市敞曹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌综膀,老刑警劉巖澳迫,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異剧劝,居然都是意外死亡橄登,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門讥此,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拢锹,“玉大人,你說(shuō)我怎么就攤上這事萄喳∽湮龋” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵他巨,是天一觀的道長(zhǎng)充坑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)染突,這世上最難降的妖魔是什么捻爷? 我笑而不...
    開(kāi)封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮份企,結(jié)果婚禮上也榄,老公的妹妹穿的比我還像新娘。我一直安慰自己薪棒,他們只是感情好手蝎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著俐芯,像睡著了一般棵介。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吧史,一...
    開(kāi)封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天邮辽,我揣著相機(jī)與錄音,去河邊找鬼。 笑死吨述,一個(gè)胖子當(dāng)著我的面吹牛岩睁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播揣云,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼捕儒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了邓夕?” 一聲冷哼從身側(cè)響起刘莹,我...
    開(kāi)封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焚刚,沒(méi)想到半個(gè)月后点弯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矿咕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年抢肛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碳柱。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捡絮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出士聪,到底是詐尸還是另有隱情锦援,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布剥悟,位于F島的核電站灵寺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏区岗。R本人自食惡果不足惜略板,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望慈缔。 院中可真熱鬧叮称,春花似錦、人聲如沸藐鹤。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)章鲤。三九已至辐益,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肄满,已是汗流浹背谴古。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工质涛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掰担。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓汇陆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親带饱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毡代,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 最近在學(xué)習(xí)RxSwift相關(guān)的內(nèi)容,在這里記錄一些基本的知識(shí)點(diǎn)勺疼,以便今后查閱月趟。 Observable 在RxSwi...
    L_Zephyr閱讀 1,756評(píng)論 1 4
  • 1.RxSwift初識(shí) RxSwift是 ReactiveX 的swift版本,是一種函數(shù)式響應(yīng)編程的框架恢口。RxS...
    MrMessy閱讀 3,176評(píng)論 0 11
  • 發(fā)現(xiàn) 關(guān)注 消息 RxSwift入坑解讀-你所需要知道的各種概念 沸沸騰關(guān)注 2016.11.27 19:11*字...
    楓葉1234閱讀 2,797評(píng)論 0 2
  • 原創(chuàng) 2017-06-13 RxSwift 這個(gè)框架RP框架相信你應(yīng)該不陌生了,在Objective-C中我們使用...
    一根聰閱讀 6,243評(píng)論 4 14
  • 彈指一揮三十年穷躁, 青蔥歲月怡無(wú)邊耕肩。 懵懂一生蒼茫路, 歌樂(lè)不絕聲不斷问潭。 萬(wàn)丈豪情起麓山猿诸, 桃子湖畔醉無(wú)眠。 待到漫...
    采葭小妖閱讀 771評(píng)論 9 11