对闭包函数的强引用问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
WildCat
V2EX    Swift

对闭包函数的强引用问题

  •  1
     
  •   WildCat 2014-11-18 23:04:39 +08:00 3924 次点击
    这是一个创建于 4044 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class Person { func goHome() { println("test") } deinit { println("Persion deinit") } } class Apartment { var somebodyCome: (() -> ())? deinit { println("Apartment deinit") } } var person: Person? = Person() var apartment: Apartment? = Apartment() apartment!.somebodyCome = person!.goHome person = nil // Output: [nothing] 

    Apartment 引用了一个 Person的方法 goHome() 作为 somebodyCome 时的动作。
    但是这会造成强引用。 不过无法写这样的语句 weak var somebodyCome: (() -> ())?
    这种情况下的最佳实践应该是什么?

    10 条回复    2014-11-21 01:32:16 +08:00
    jakwings
        1
    jakwings  
       2014-11-19 00:52:56 +08:00
    为什么不引用Person而是引用函数?反正对象销毁的时候你也不需要那个函数了吧,而当函数还有用的时候对象也依然存在着。
    jakwings
        2
    jakwings  
       2014-11-19 01:03:49 +08:00
    @jakwings 不对,我应该说你已经违反了面向对象编程的重要原则,增加了不必要的耦合度,没有让对象各施其职。
    WildCat
        3
    WildCat  
    OP
       2014-11-19 07:36:18 +08:00 via iPhone
    @jakwings 没有吧,我这里的实际需求是,一个 Custom View 的发生变化的时候(类似 TabView 左滑动到上一页),通知Controller. 一般的做法是用 delegate + protocol ,这里我想直接用 Closure 。
    但是我在 Controller 里打算用一个函数而不是闭包。主要是增加易读性。

    没有增加耦合吧
    jakwings
        4
    jakwings  
       2014-11-19 12:52:00 +08:00   1
    @WildCat apartment直接调用了person的method,而不是让person去调用,明显是越权了。而且强弱引用只能应用到class上面,你也没有什么别的办法了。在调用的时候,虽然函数使用的self依然是指向person,但是总感觉怪怪的,不知道self能否保证永远指向person,官方教程上貌似没有说到。
    WildCat
        5
    WildCat  
    OP
       2014-11-19 18:36:58 +08:00
    @jakwings https://github.com/HeshamMegid/HMSegmentedControl/blob/master/HMSegmentedControlExample/HMSegmentedControlExample/ViewController.m

    63~68 行:

    既然在 Swift 中函数也是一等公民,我想把 indexChangeBlock 设置为 ViewController 的实例方法. 这样不合法吗?
    jakwings
        6
    jakwings  
       2014-11-19 19:13:03 +08:00   1
    @WildCat method虽然也是函数,可它是属于对象/实例的,你可以让一个固定的method对self进行unowned吗?假如不行的话,就和相应对象/实例脱不了身了。可以考虑把那个method用closure替代,在初始化时添加好,不绑死在对象上。
    jakwings
        7
    jakwings  
       2014-11-19 19:42:40 +08:00
    对了,我这测试怎么也没output,deinit函数里的println好像没用,我改用全局变量count统计了。

    http://code.bulix.org/ijoun1-87439
    jakwings
        8
    jakwings  
       2014-11-19 19:47:41 +08:00
    @jakwings 看来不故意设置变量为nil的话deinit里的输出是会被抛弃的,不知道这算不算是bug,或者说程序是在释放了println函数之后才开始对象的销毁操作……
    WildCat
        9
    WildCat  
    OP
       2014-11-19 20:04:21 +08:00   1
    @jakwings 不能用 Playground , Playground 会自动引用全局的对象。
    jakwings
        10
    jakwings  
       2014-11-21 01:32:16 +08:00
    @WildCat 那用xcrun swift test.swift执行呢?我这样做同样在程序结束时没有deinit的输出,在程序结束前自行设为nil就有。我觉得好像和全局对象无关吧?我在SO那里问了:
    https://stackoverflow.com/questions/27044573/swift-no-output-for-println-in-deinit-method
    关于     帮助文档     自助推广系统     博客   &nsp; API     FAQ     Solana     3026 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 12:44 PVG 20:44 LAX 04:44 JFK 07:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86