【问题标题】:Appearance proxies / UI_APPEARANCE_SELECTOR in Swift?Swift 中的外观代理/UI_APPEARANCE_SELECTOR?
【发布时间】:2014-10-02 22:17:38
【问题描述】:

Apple 文档指出:

要参与外观代理 API,请标记您的外观 带有 UI_APPEARANCE_SELECTOR 的标题中的属性选择器。

在 Objective-C 中,可以像这样使用 UI_APPEARANCE_SELECTOR 注释属性:

@property (nonatomic, strong) UIColor *foregroundColor UI_APPEARANCE_SELECTOR;

如何在 Swift 中做同样的事情?

【问题讨论】:

    标签: swift uikit uiappearance


    【解决方案1】:

    将您的自定义视图属性标记为dynamic

    例如:

    class YourCustomView: UIView {
        @objc dynamic var subviewColor: UIColor? {
            get { return self.yourSubview.backgroundColor }
            set { self.yourSubview.backgroundColor = newValue }
        }
        ...
    }
    

    然后:

    YourCustomView.appearance().subviewColor = UIColor.greenColor()
    

    【讨论】:

    • 我需要尝试一下。它是否记录在某处?
    • 据我所知,它没有记录在案,但我试过了,它奏效了。基本上,从 Objective-C 框架动态访问的 Swift 属性应该被标记为动态的。 UI_APPEARANCE_SELECTOR 只是代码补全的编译器注解,对运行时没有影响。检查 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer‌​/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAppeara‌​nce.h
    • 不幸的是,它不适用于 Xcode 8.3.2 iOS 9.1 中的 UIBarButton 子类,并且在我设置外观并实例化新的自定义 UIBarButtonSubclass 后导致 UIKit 崩溃
    • 还需要在属性中添加@objc属性才能生效。
    【解决方案2】:

    我没有找到解决方案,但找到了解决方法。 我没有对属性进行注释,而是将它们作为类变量。

    private struct StarFillColor { static var _color = UIColor.blackColor() }
    internal class var starFillColor: UIColor {
        get { return StarFillColor._color }
        set { StarFillColor._color = newValue }
    }
    

    在我设置所有外观的文件中:

    MyClass.starFillColor = UIColor.r(181, g: 60, b: 109) 
    

    希望对大家有所帮助!

    【讨论】:

      【解决方案3】:

      根据以前的答案,这是我实现的 UIView 扩展,用于管理带有视图边框的 UIView 外观,我希望它可以帮助某人:

      extension UIView {
          @objc dynamic  var borderColor: UIColor? {
              get {
                  if let color = self.layer.borderColor {
                      return UIColor(cgColor: color)
                  } else {
                      return nil
                  }
              }
              set(color) {
                  self.layer.borderColor = color?.cgColor
              }
          }
      
          @objc dynamic  var borderWidth: NSNumber? {
              get { return NSNumber(value: Float(self.layer.borderWidth))}
              set(width) {
                  self.layer.borderWidth = CGFloat(width?.floatValue ?? 0)
              }
          }
      
          @objc dynamic  var cornerRadius: NSNumber? {
              get { return NSNumber(value: Float(self.layer.cornerRadius))}
              set(radius) {
                  self.layer.cornerRadius = CGFloat(radius?.floatValue ?? 0)
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        在 Swift 中,您不需要(实际上,您不能)用 UI_APPEARANCE_SELECTOR 注释属性。

        只需确保您的外观属性访问器方法采用以下形式:

        func propertyForAxis1(axis1: IntegerType, axis2: IntegerType, axisN: IntegerType) -> PropertyType
        func setProperty(property: PropertyType, forAxis1 axis1: IntegerType, axis2: IntegerType)
        

        来源:Apple Documentation

        例如:

        func setStarViewColor(color: UIColor) {
            self.backgroundColor = color
        }
        

        然后你可以像这样设置你的外观属性:

        MyView.appearance().setStarViewColor(someColor)
        

        我目前在我的 Swift 项目中使用这个解决方案,它可以工作,希望它对你也有帮助。

        【讨论】:

        • 嗨,你能把你正在使用的课程贴出来吗!我似乎无法正确调用我的二传手,尝试调用它时我得到一个BAD_ACCESS。我想知道我是否正确地声明了我的类,它是UIButton 的子类,并且我符合UIAppearanceContainer 就像它在文档中所说的那样!干杯!
        • @Rich Checkout 我的gist,包括全班,希望对您有所帮助。
        • 不幸的是,这不允许我更改特定实例的颜色。知道如何实现吗?谢谢!
        • 遗憾的是,对此的回应很晚,但我发现将方法标记为动态解决了 UIButton 的 BAD_ACCESS 问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 2021-12-01
        • 2019-07-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多