在Swift

时间:2016-07-21 15:56:05

标签: ios swift uikit nsattributedstring uiappearance

根据NSHipster,#34;让自定义UI类符合UIAppearance不仅是一种最佳实践,而且还表明了对其实施的一定程度的关注。"

因此,我尝试将文本属性(稍后用于创建NSAttributedString)设置为var titleTextAttributes: [String : AnyObject]?子类中的属性UIView,如下所示:

func applyAppearance() {

    UINavigationBar.appearance().translucent = true
    UINavigationBar.appearance().tintColor = UIColor(named: .NavBarTextColor)
    UINavigationBar.appearance().barTintColor = UIColor(named: .NavBarBlue)
    UINavigationBar.appearance().titleTextAttributes = [
        NSForegroundColorAttributeName: UIColor(named: .NavBarTextColor),
        NSFontAttributeName: UIFont.navBarTitleFont()!
    ]

    ActionBarView.appearance().backgroundColor = UIColor(white: 1, alpha: 0.15)
    ActionBarView.appearance().titleTextAttributes = [
        NSKernAttributeName: 1.29,
        NSFontAttributeName: UIFont.buttonFont()!,
        NSForegroundColorAttributeName: UIColor.whiteColor(),
    ]
}

这是从我的AppDelegate剪下来的。

现在,在尝试设置ActionBarView.appearance().titleTextAttributes = [ ... ]时,我收到以下运行时错误:

error when trying to set text attirbutes on a custom uiview subclass

值得一提的是,在UINavigationBar上设置属性可以毫无问题地工作。

转到UINavigationBar的头文件会显示:

/* You may specify the font, text color, and shadow properties for the title in the text attributes dictionary, using the keys found in NSAttributedString.h.
 */
@available(iOS 5.0, *)
public var titleTextAttributes: [String : AnyObject]?

ActionBarView类中的属性完全相同:

class ActionBarView: UIView {

    var titleTextAttributes: [String : AnyObject]?

    // ...
}

所以我的问题是:我可以用自己的UIView子类中的文本属性字典实现属性,可以通过UIAppearance代理设置吗? 由于在Swift中无法使用UI_APPEARANCE_SELECTOR吗?为什么它对于像UINavigationBar这样的UIKit类来说是开箱即用的?是否涉及某种黑魔法?

2 个答案:

答案 0 :(得分:4)

对于外观属性,只需添加动态关键字:

class ActionBarView: UIView {

    dynamic var titleTextAttributes: [String : AnyObject] = [:]

    // use ActionBarView.appearance().titleTextAttributes 
}

和外观属性访问器方法必须是form:

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

答案 1 :(得分:3)

基于this answer,将属性titleTextAttributes标记为dynamic并将其作为存储使用另一个作为存储来解决问题:

class ActionBarView: UIView {

    /// UIAppearance compatible property
    dynamic var titleTextAttributes: [String : AnyObject]? { // UI_APPEARANCE_SELECTOR
        get { return self._titleTextAttributes }
        set { self._titleTextAttributes = newValue }
    }

    private var _titleTextAttributes: [String : AnyObject]?

    // ... use `self.titleTextAttributes` in the implementation
}