Eureka で文字色を変えれる Section Header/Footer

設定風画面を簡単に構築できる [Eureka](https://github.com/xmartlabs/Eureka) という有名なiOSライブラリ。
UI系のライブラリはあまり使いたくないんですが、これはわりかし使ってます。

このライブラリで、Section の Header / Footer の文字色を気軽に変更したかったのですが思ったより手軽にできなかったので記事にしておきます。



# 環境

|Xcode|iOS|Swift|Eureka|
|:--:|:--:|:--:|:--:|
|10.1|12.1|4.2|4.3.1|

Eureka は Carthage 経由で導入

# 前提

- この `もじれつ` の文字色を変えたい

```swift
form +++ Section(footer: "もじれつ")
```

- 新たなUIViewクラス/IBファイルを作らず済ませたい (精神衛生上)

ちなみに独自クラスを用意する場合、下記のようにします。詳しくは [README](https://github.com/xmartlabs/Eureka#section-header-and-footer) で。

```swift
Section() { section in
    // xib ファイルから使う場合
    section.header = HeaderFooterView<MyHeaderNibFile>(.nibFile(name: "MyHeaderNibFile", bundle: nil))
    // コードから使う場合
    section.header = HeaderFooterView<MyCustomUIView>(.class)
}
```

- Autolayout を使用して高さ可変にしたい

# コード

```swift
import Eureka

extension Section {
    
    convenience init(colorChangeableFooter: String) {
        self.init { section in
            var footer = HeaderFooterView<UIView>(.class)
            footer.height = { UITableView.automaticDimension }
            footer.onSetupView = { view, _ in

                // 解説1
                if let label = view.subviews.compactMap({ $0 as? UILabel }).first {
                    label.text = colorChangeableFooter
                    return
                }
                
                let label = UILabel()
                label.translatesAutoresizingMaskIntoConstraints = false // 解説2
                label.textColor = .white
                label.text = colorChangeableFooter
                label.font = UIFont.systemFont(ofSize: 13)
                label.numberOfLines = 0
                
                view.addSubview(label)
                view.topAnchor.constraint(equalTo: label.topAnchor, constant: -8).isActive = true
                view.bottomAnchor.constraint(equalTo: label.bottomAnchor, constant: 8).isActive = true
                view.leftAnchor.constraint(equalTo: label.leftAnchor, constant: -15).isActive = true
                view.rightAnchor.constraint(equalTo: label.rightAnchor, constant: 15).isActive = true
            }
            section.footer = footer
        }
    }
    
    var colorChangeableFooterLabel: UILabel? {
        return self.footer?.viewForSection(self, type: .footer)?.subviews.compactMap({ $0 as? UILabel }).first
    }
}

// 使用したい箇所で
form +++ Section(colorChangeableFooter: "文字列")

// 色を変更する時 (該当Sectionインスタンスが section だとして)
section.colorChangeableFooterLabel?.textColor = .red
```

# 解説

## 1. onSetupView は複数回呼ばれる
複数回呼ばれる可能性があるのに何度もインスタンス生成して `addSubview` していたら良くないので、
`subviews` にあるかを確認してます。

## 2. Autoresizing Mask と Auto Layout
`translatesAutoresizingMaskIntoConstraints` を `false` にしとかないと、Autoresizing Mask の制約が勝手に Auto Layout の制約に変換されてしまって、うまくいきません。
これに気づくのに時間がかかりました。

## 3. その他
新たな UIView 継承クラスを作りたくないがためにこんなことをしていますが、本来 `onSetupView` 内で `addSubview` とかをするの自体があんまりよろしくないと思います。(色や文字の変更などをすべき場所。)

今回はただ文字色を変更したいだけだったのでこのようにしましたが、記事を書いといてなんですが独自クラスを用意したほうが良いと思います。



# 参考
- [https://qiita.com/star_aman/items/a62de36a3ce66d318b10#autoresizingmaskとの競合](https://qiita.com/star_aman/items/a62de36a3ce66d318b10#autoresizingmask%E3%81%A8%E3%81%AE%E7%AB%B6%E5%90%88)
- https://github.com/xmartlabs/Eureka/issues/452
- https://github.com/xmartlabs/Eureka/issues/379#issuecomment-260669462