Swift 状態に応じてbutton の表示を切り替え、ローカライズも

f:id:happy_teeth_ago:20181014114219p:plain

このnameボタンは状態を持っている。

それを状態に応じて表示を切り分ける。

接続はこう

@IBOutlet weak var uiNameSorter: UIButton!
   /// 複合構成点データをロードする
    private func fetchPolyNodes() {
        let polyTypes = [PolyType.MapLot,PolyType.MapRoute]
        ofPolyNodes.disconnect()
        ofPolyNodes.fetch(CdPolyNode.fetchRequestFor(
            ofPolyNodes.previousRequest,polyTypes,typeNumAsc: !uiNameSorter.isSelected))
      //ここで値をセット
        uiNameSorter.setTitle("name↑", for: .selected)
        uiNameSorter.title(for: .selected)
    }

しかしこれでは、英語以外の言語でもすべて"name↑"と表示されてしまう。 よってメッセージの定数を宣言し、そこにセットするだけ

NSLocalizedStringを利用する。

   let str: String = NSLocalizedString("MsrMsgUINameSorter", comment: "")
        uiNameSorter.setTitle( str, for: .selected)
        uiNameSorter.title(for: .selected)

commentはキーとバリューには関係ないので、なしで良い。必要があれば記載する そして Localizable.strings(Japanese)にキーとバリューを記載する(ちなみにbaseは必ず英語) f:id:happy_teeth_ago:20181015110311p:plain

//Base
"MsrMsgUINameSorter" = "name↑";
//Japanese
"MsrMsgUINameSorter" = "名前↑";

これで完成!

通常のボタンタイトルのセット

 button.setTitle("ボタンおしてね!", for: .normal) // ボタンのタイトル

関数定義はこれ

f:id:happy_teeth_ago:20181014115955p:plain

余談ですが、日本人のプログラム能力が低いのは、リファレンスを読まないからと、聞いたのでなるべくリファレンスを参照することにしました。ブログ読んで、エラーがなくなったら良しとしているから、米国と差がつくのだそうです。

simplearchitect.hatenablog.com

通常はボタンにsetTitleするだけ。

UIControl.Stateにはつぎの状態を保持できる。

f:id:happy_teeth_ago:20181014120501p:plain

ソースに戻ります。

表示のたびにfetchをかける

ボタンの状態を取得するために、フェッチ用の関数を作る。

fetchRequestForのところで呼び出している

   static func fetchRequestFor(
        _ request: NSFetchRequest<CdPolyNode>?,
        _ types: [PolyType],
        typeNumAsc: Bool = true
//CdPolyNodeはDB
        ) -> NSFetchRequest<CdPolyNode> {
        let predicate = buildPredicate(types, nil, nil)
        return fetchRequestFor(request, predicate, typeNumAsc:typeNumAsc)
    }

CdPolyNodeの拡張

NSPredicateを返す。今回は他にも返したい値があるので、関数を作成。
 static func buildPredicate(_ types: [PolyType], _ format:String?, _ args:[Any]?) -> NSPredicate {
        var boundArgs:[Any] = [types.map({$0.rawValue})]
        var boundFormat = "\(#keyPath(CdPolyNode.type)) IN %@"
        if let _format = format , !_format.isEmpty {
            if let _args = args { boundArgs.append(contentsOf: _args)}
            boundFormat = boundFormat + " AND \(_format)"
        }
        return NSPredicate(format: boundFormat, argumentArray: boundArgs)
    }

ローカライズはxcode10.0 より全く新しくなったので、これを見ておいたほうが良い。 12分位から、実装の説明がある。

developer.apple.com

忘備録のため、かなりわかりにくい説明となっている点、ご了承ください。