V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
troyl
V2EX  ›  iDev

面试的时候被问到了一个关于 class method 的问题

  •  
  •   troyl · 2014-07-09 08:43:40 +08:00 · 4375 次点击
    这是一个创建于 3580 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如何创建一个 class method 使得所有这个 class 的 instance 的某一 property 都被更新。
    比方说,改掉所有 Label 的 default height
    第 1 条附言  ·  2014-07-09 10:15:33 +08:00
    面的是 Objective-C
    25 条回复    2014-07-10 14:28:12 +08:00
    ledkk
        1
    ledkk  
       2014-07-09 09:26:58 +08:00
    把自己的实例放到一个类变量上, 修改属性的类方法,就是遍历所以的类实例,然后修改属性
    fgwww
        2
    fgwww  
       2014-07-09 09:57:32 +08:00   ❤️ 1
    做成单例
    bbiao
        3
    bbiao  
       2014-07-09 10:13:07 +08:00
    有没有设定语言背影?
    C++?
    JavaScript?
    troyl
        4
    troyl  
    OP
       2014-07-09 10:13:43 +08:00
    @bbiao 这里不是 iDev 么?当然是 Objective-C 啊
    bbiao
        5
    bbiao  
       2014-07-09 10:15:04 +08:00
    @troyl 好吧,我在首页上看到的问题,没注意版块。
    troyl
        6
    troyl  
    OP
       2014-07-09 10:15:57 +08:00
    @bbiao :)
    hoogle
        7
    hoogle  
       2014-07-09 10:25:40 +08:00 via iPhone
    用通知会比较方便
    troyl
        8
    troyl  
    OP
       2014-07-09 10:26:57 +08:00
    @hoogle 已经强制要求要用 class method 了……
    nagato
        9
    nagato  
       2014-07-09 10:33:08 +08:00
    initWithHeight: ?
    troyl
        10
    troyl  
    OP
       2014-07-09 10:50:20 +08:00
    @nagato 那是创建一个新的 instance 的时候 height 会改变,已有的不会变啊。
    hoogle
        12
    hoogle  
       2014-07-09 11:13:07 +08:00
    @troyl class method 里postNotification, instance method里addObserve。。
    nekop
        13
    nekop  
       2014-07-09 11:14:44 +08:00
    事先有保存改类的所有实例吗?
    zichen0422
        14
    zichen0422  
       2014-07-09 11:23:53 +08:00
    猜测一下 没有实现过 如有错误 请无视

    class_copyPropertyList 这个可以获取类的属性
    class method 方法去遍历类的属性 uilabel的就对其改变height。
    icyalala
        15
    icyalala  
       2014-07-09 11:26:25 +08:00
    @Kjuly 这个太局限了吧~

    对于不能接触源码的类、难以子类化的类簇,我感觉可以这样,具体行不行还没试:
    创建个Category,写上+load方法,然后里面用method swizzling去拦截类创建的方法,或者去拦截那个property的访问方法,之后用proxy或者notification之类的机制去实现更新动作。


    如果能子类化、或者能接触源码,那就很简单了。最简单的方法就是修改init之类的创建方法,在实例创建后把它添加到一个全局的Array里,dealloc时从全局Array里移除,这样就能得到当前类的全部实例了。当然用notification什么的也都可以了。
    Kjuly
        16
    Kjuly  
       2014-07-09 11:39:58 +08:00
    @icyalala "UIAppearance is a protocol that returns a proxy that will forward any configuration to instances of a particular class."

    - |+appearance|: Returns the appearance proxy for the receiver.
    - |+appearanceWhenContainedIn:(Class <UIAppearanceContainer>)ContainerClass,...|: Returns the appearance proxy for the receiver in a given containment hierarchy.

    對於問題足夠了,不用做多餘的hack ;)
    troyl
        17
    troyl  
    OP
       2014-07-09 11:48:52 +08:00
    @Kjuly 那个 UILabel 只是打个比方……如果是其他 custom 的 class 呢?
    troyl
        18
    troyl  
    OP
       2014-07-09 12:02:55 +08:00
    @icyalala 按照面试官的意思是可以接触源码的。但是如果改 initializer 然后储存所有的 instance 到一个 NSArray,之后再遍历修改所有的 height 值似乎有点笨……我的意思是能不能搞一个全局变量,然后在 initializer 里把所有的 height property 都指向这个全局变量,然后想修改的话就修改这个全局变量就行了。
    Kjuly
        19
    Kjuly  
       2014-07-09 12:16:01 +08:00
    @troyl 任意class的property.
    krafttuc
        21
    krafttuc  
       2014-07-09 13:48:33 +08:00
    最容易想到的是通过 class variable 来实现。可惜,Objective-C 严格来说是不像 C++, Java 有那种 class variable 的特性。只有全局的 static variable,也就是 C-style 的那种全局变量。但我们仍然可以尝试用 class methods 来操纵这些 static variable。。。

    接着用 instance methods,如各种 accessor (property就是一种)方法,来读这些个 static 变量,这样可以实现某种程度上的 property 更新了。


    @Kjuly UIAppearance 在语义上是用于定制UI外观的,因此我不建议用在非UI层面的类上。此外,UIAppearance 的 + appearance 方法是返回一个实例吧?!接着在设置一些值时貌似在实例上操作,而非通过楼主题目所要求的 class methods 了?
    Kjuly
        22
    Kjuly  
       2014-07-09 14:46:29 +08:00
    @krafttuc 問題說簡單了就是創建一個實現統一更新指定參數的邏輯的Class Method 那把所有更新操作放在裏邊 比如|+updateToNightMode|.

    至於「UIAppearance 在语义上是用于定制UI外观的」 沒錯 但請問在iOS開發上 除了UI需要統一更新外 還有什麼?哪怕很多邏輯參數上的更新 最後也是體現在UI/UX上 當然也肯定有特例 那麼就相應尋找其它解決方案

    不多繼續討論這個問題了 我也是根據自己知道的推薦一個方法 ;)
    zhigang1992
        23
    zhigang1992  
       2014-07-10 09:42:05 +08:00
    没人说到Objective-C的动态功能? 在+load里面把instance的method imp替换掉?比如height的getter?
    dopcn
        24
    dopcn  
       2014-07-10 14:00:44 +08:00
    class method 里postNotification, instance method里addObserve
    这个方法似乎更实际一些
    将 class conform to UIAppearanceContainer 标记需要统一变动的 property 为 UI_APPEARANCE_SELECTOR,然后用 appearance 应该就可以改动所有了,但只是理论上可行
    troyl
        25
    troyl  
    OP
       2014-07-10 14:28:12 +08:00
    @dopcn 这个思路很不错诶!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1090 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 23:18 · PVG 07:18 · LAX 16:18 · JFK 19:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.