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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

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