NSTextFieldをAutoLayoutで配置すると幅が0になっちゃう
最近趣味プログラミングでAppKitを触っている。
AppKitについて言いたいことはいろいろあるがUILabel代わりに使ったNSTextFieldについてハマったので書いておく。
Slackのメッセージみたいな見た目のビューを作りたくてAutoLayoutでごちゃごちゃ配置してたらNSTextFieldの幅がゼロになってしまって困った。
目指していた形はこんなの。
で、当初ふつうに配置して制約かけたら
こんなんなった。Xcodeのビューの階層見れるアレ(名前知らん)で見たらこんなん。
いる。
幅0のNSTextField2つと、なんか中途半端に生き残ったNSTextFieldがいる。
最初に疑ったのはAutoLayoutで、自分で書けた制約のプライオリティとか、Content Compression Resistance Priorityなんかを気にしていろいろいじってみたが全然改善されず、1時間くらい浪費した。
Content Compression Resistance Priorityについて調べなおしていたら、intrinsicContentSize
にたどり着いた。
Custom views typically have content that they display of which the layout system is unaware. Setting this property allows a custom view to communicate to the layout system what size it would like to be based on its content. This intrinsic size must be independent of the content frame, because there’s no way to dynamically communicate a changed width to the layout system based on a changed height, for example.
つまりContent Compression Resistance Priorityで登場するビューの固有サイズというのはこいつのことらしい。かけられた制約が固有サイズより大きかった時の固有サイズの優先度がContents Hugging Priority、逆に制約が固有サイズより小さかった時の固有サイズの優先度がContents Compression Resistance Priorityということだ。
で、stringValue
をセットしたあとのNSTextFieldのintrinsicContentSize
を見ると
AppKitの一番気に入らない部分の真似します
— ひらり (@hiragram) 2016年8月18日
(lldb) po nameLabel.intrinsicContentSize
— ひらり (@hiragram) 2016年8月18日
▿ CGSize
- width : -1.0
- height : 21.0
width: -1.0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
— ひらり (@hiragram) 2016年8月18日
自分でかけた制約に問題はなく、Content Compression Resistance Priorityにも問題はなく(そもそも触ってない)、AutoLayoutやめてsizeToFit()
でサイズ決めて配置したとしてもintrinsicContentSize
のwidthは-1.0なので見えないままでしたよ、という結構きついハマりだった。
対応めんどくさかったら投げ出して帰るつもりだったが、StackOverflowにまさにその回答があった。
-[NSTextField intrinsicContentSize] always has undefined width - StackOverflow
この一番voteを稼いでる回答(というか質問者が自己解決したっぽい)によると、
OK, finally figured it out…
[_textfield setEditable:NO]
That's it. I guess that with an editable textfield one must have an explicit constraint for the textfield width. Which kind of makes sense, imagine editing a textfield and it would constantly grow horizontally with every keystroke... not an ideal UI.
僕はSwiftなので
nameLabel.editable = false
これでいけた。他のNSTextFieldも同じ。
Content Compression Resistance Priorityが具体的にどう動くのかを把握してなかったので時間くってしまった。
AutoLayoutに関して僕が良いなと思ったおすすめの本はこちら。
よくわかるAuto Layout iOSレスポンシブデザインをマスター
- 作者: 川邉雄介,所友太
- 出版社/メーカー: リックテレコム
- 発売日: 2016/06/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
いやーはまったはまった。