RxSwift(4) 练习

图片发自简书App

经过了几天的学习,边看文档边敲代码,顺便把一些代码记录下来,以备后面温习。
先看一个delay函数

 func delay(delay:Double, closure:()->()) {
        dispatch_after(
            dispatch_time(
                DISPATCH_TIME_NOW,
                Int64(delay * Double(NSEC_PER_SEC))
            ),
            dispatch_get_main_queue(), closure)
    }

concat

*在已有的sequence 中加入另外一个sequence *

 let a  = Variable(1)
        let b  = Variable(2)
       // let d = Variable(100)
        
        let f = Variable("sun->concat")
        
        _ = Observable.combineLatest(a.asObservable(), b.asObservable()) { (intA, IntB) -> Int in
            print("......1  ...>>= \\(intA )  b= \\(IntB)")
            return intA + IntB
        }.map { (intAB) -> String in
            print("......2")
            return String(intAB)
        }.concat(f.asObservable())// map 返回String,这里使用a,b 就不行
        .filter { (str) -> Bool in
            print("......3")
            return str.characters.count > 0
            
        }.subscribeNext { (value) -> Void in
            print("......4")
            print("value ==== \\(value)")
        }


输出如下:

......1  ...>>= 1  b= 2
......2
......3
......4
value ==== 3
这里concat 还没有emit 任何的item 所以不会触发print
但是由于a,b 都已经有了初始值所以只要subscribe 就会执行print
map ,filter 操作都会执行。如果是concat 生成的observable 触发的操作只执行后面的filter
 

再看另外一个操作

 a.value = 100
        delay(2) { () -> () in
            print("after 2 second...")
            f.value = "sunjianfeng"
}

这样的输出如下:

......1  ...>>= 1  b= 2
......2
......3
......4
value ==== 3
......1  ...>>= 100  b= 2
......2
......3
......4
value ==== 102
......3
......4
value ==== sun->concat
after 2 second...
......3
......4
value ==== sunjianfeng

注意如果仅仅是 a.value = 100 没有delay的操作,仅仅会执行a,b的输入输出.

总结: 对生成的observable 进行的操作如同一个管道一样,都会按顺序执行
combinlatest-observable->map->filter->print

concat-Observable->filter->print

Dispose

每一个subscriber 一旦subscription 就会生成一个单独的元素序列,我们定义的Observable的操作函数(operator) 一般是无状态的,只有subscribe 后才会变成有状态的(大多数的操作函数是无状态的)

我们先定义了一个operator (myInterval),返回一个匿名的Dispose,当我们手动dispose 后改计数器停止工作。

func myInterval (interval:NSTimeInterval)-> Observable<Int>{
        return Observable.create({ (observer) -> Disposable in
            print("Subscribed")
            let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
            let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0,queue);
            
            var next = 0;
            dispatch_source_set_timer(timer, 0, UInt64(interval * Double(NSEC_PER_SEC)), 0)
            
            let cancel = AnonymousDisposable {
                print("Disposed")
                dispatch_source_cancel(timer)
            }
            dispatch_source_set_event_handler(timer, {
                if cancel.disposed {
                    return
                }
                observer.on(.Next(next))
                next += 1
            })
            dispatch_resume(timer)
            return cancel
        })
    }

先尝试一下这个, 指定1秒间隔,5秒后停止

  let counter = myInterval(1);
        print("started .....")
        let subscription = counter.subscribeNext { (n) -> Void in
            print(n)
        }
        NSThread.sleepForTimeInterval(5)
        subscription.dispose()
        print("end ....")

输出:

started .....
        Subscribed
        0
        1
        2
        3
        4
        Disposed
        end ....
        

再改一下,订阅两次

func testMyInterval2(){
        let counter = myInterval(0.1)
        
        print("Started ----")
        
        let subscription1 = counter
            .subscribeNext { n in
                print("First \\(n)")
        }
        let subscription2 = counter
            .subscribeNext { n in
                print("Second \\(n)")
        }
        
        NSThread.sleepForTimeInterval(0.5)
        
        subscription1.dispose()
        
        NSThread.sleepForTimeInterval(0.5)
        
        subscription2.dispose()
        
        print("Ended ----")
    }

输出:

 /**
        Started ----
        Subscribed
        Subscribed
        First 0
        Second 0
        First 1
        Second 1
        Second 2
        First 2
        Second 3
        First 3
        Second 4
        First 4
        Disposed
        
        这是第二个
        Second 5
        Second 6
        Second 7
        Second 8
        Second 9
        Disposed
        Ended ----
        */

这说明每一个subscribe后都会生成一个单独的sequence

自定义 函数

  func myJust<E>(element:E)-> Observable<E> {
        return Observable.create({ (observer) -> Disposable in
            observer.on(Event.Next(element))
            observer.on(.Completed);
            return NopDisposable.instance;
        })
    }
 myJust(0)
            .subscribeNext { n in
                print(n)
        }

sharing Subscription and shareReplay operator

 let counter = myInterval(0.1)
            .shareReplay(1)
        
        print("Started ----")
        
        let subscription1 = counter
            .subscribeNext { n in
                print("First \\(n) ")
        }
        let subscription2 = counter
            .subscribeNext { n in
                print("Second \\(n) ")
        }
        
        NSThread.sleepForTimeInterval(0.5)
        
        subscription1.dispose()
        
        NSThread.sleepForTimeInterval(0.5)
        
        subscription2.dispose()
        
        print("Ended ----")
        /**
        Started ----
        Subscribed
        First 0
        Second 0
        First 1
        Second 1
        First 2
        Second 2
        First 3
        Second 3
        First 4
        Second 4 
        Second 5 
        Second 6 
        Second 7 
        Second 8 
        Second 9 
        Disposed
        Ended ----
        
       一个disposed
      

自定义operator

extension ObservableType{
    func myMap<R>(transformK :E -> R)-> Observable<R>{
        return Observable.create { (observer) -> Disposable in
            let subscription = self.subscribe
                { (event) -> Void in
                switch event{
                  
                case .Next(let value):
                     let result = transformK(value)
                    observer.on(.Next(result))
                   
                case .Error (let error):
                    observer.on(.Error(error))
                   
                case .Completed :
                    observer.on(.Completed)
                }
            }
             return subscription
        }
    }
}

/*
let subscription = myInterval(0.1)
.myMap { e in
return "This is simply \\(e)"
}
.subscribeNext { n in
print(n)
}
*/

Debugging memory leaks

In debug mode Rx tracks all allocated resources in a global variable resourceCount.In case you want to have some resource leak detection logic, the simplest method is just printing out RxSwift.resourceCount periodically to output.

 /* add somewhere infunc application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool*/ 
_ = Observable<Int>.interval(1, scheduler: MainScheduler.instance) .subscribeNext { _ in print("Resource count \\(RxSwift.resourceCount)")
 }

Most efficient way to test for memory leaks is:

  • navigate to your screen and use it
  • navigate back
  • observe initial resource count
  • navigate second time to your screen and use it
  • navigate back
  • observe final resource countIn case there is a difference in resource count between initial and final resource counts, there might be a memoryleak somewhere.

The reason why 2 navigations are suggested is because first navigation forces loading of lazy resources.

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 124,691评论 18 136
  • 倦了,不要放弃 其实放弃的不是一些事物 是自己,珍惜自己 烦了,不要抱怨 上天不知道你是谁 要好好生活 享受你正在...
    最热话题精选阅读 6,049评论 0 50
  • 日念家人一好处,念力加持享幸福! 【念夫好】本来是打算给爸做荞面猫耳朵吃的,可雨下个不停,店铺都关门了!只好给爸吃...
    风潇潇blj阅读 86评论 0 0
  • 忆昔日,汉相诸葛,前后出师,震慑环宇,四海无不举手称赞。时值宋难,亦流传,放翁夸赞“出师一表真名世,千载谁堪伯仲间...
    ecbbebb97102阅读 352评论 1 2
  • 厨神日记第一天,红烧排骨 第二天,黑椒蘑菇羊肉,加羊汤
    王珏777阅读 100评论 0 1