UINavigationBar
私が克服しようとしている小さな問題があります。ビュー コントローラーでメソッドを使用してステータス バーを非表示にprefersStatusBarHidden()
すると (アプリ全体のステータス バーを無効にしたくありません)、ナビゲーション バーは、ステータス バーに属する高さの 20pt を失います。基本的にナビゲーションバーは縮小します。
さまざまな回避策を試していましたが、それぞれに欠点があることがわかりました。次に、メソッドのスウィズリングを使用して、この問題を解決するクラスに呼び出されるプロパティを追加するこのカテゴリに出会いました。Objective-C でテストしたところ、動作しました。元の Objective-C コードのヘッダーと実装を次に示します。fixedHeightWhenStatusBarHidden
UINavigationBar
今は Swift でアプリを作成しているので、Swift に翻訳してみました。
私が最初に直面した問題は、Swift 拡張機能がプロパティを格納できないことでした。fixedHeightWhenStatusBarHidden
そのため、値を設定できるようにするプロパティを宣言するには、計算されたプロパティで解決する必要がありました。しかし、これは別の問題を引き起こします。どうやら、計算されたプロパティに値を割り当てることはできません。そのようです。
self.navigationController?.navigationBar.fixedHeightWhenStatusBarHidden = true
エラーCannot assign to the result of this expression が表示されます。
とにかく以下は私のコードです。エラーなしでコンパイルできますが、動作しません。
import Foundation
import UIKit
extension UINavigationBar {
var fixedHeightWhenStatusBarHidden: Bool {
return objc_getAssociatedObject(self, "FixedNavigationBarSize").boolValue
}
func sizeThatFits_FixedHeightWhenStatusBarHidden(size: CGSize) -> CGSize {
if UIApplication.sharedApplication().statusBarHidden && fixedHeightWhenStatusBarHidden {
let newSize = CGSizeMake(self.frame.size.width, 64)
return newSize
} else {
return sizeThatFits_FixedHeightWhenStatusBarHidden(size)
}
}
/*
func fixedHeightWhenStatusBarHidden() -> Bool {
return objc_getAssociatedObject(self, "FixedNavigationBarSize").boolValue
}
*/
func setFixedHeightWhenStatusBarHidden(fixedHeightWhenStatusBarHidden: Bool) {
objc_setAssociatedObject(self, "FixedNavigationBarSize", NSNumber(bool: fixedHeightWhenStatusBarHidden), UInt(OBJC_ASSOCIATION_RETAIN))
}
override public class func load() {
method_exchangeImplementations(class_getInstanceMethod(self, "sizeThatFits:"), class_getInstanceMethod(self, "sizeThatFits_FixedHeightWhenStatusBarHidden:"))
}
}
fixedHeightWhenStatusBarHidden()
途中のメソッドはコメントアウトされています。これを残すと、メソッドの再宣言エラーが発生するためです。
これまで Swift や Objective-C でメソッドの入れ替えを行ったことがないため、この問題を解決するための次のステップがわからないか、まったく可能でさえありません。
誰かがこれに光を当てることができますか?
ありがとうございました。
更新 1: newacct のおかげで、プロパティに関する最初の問題が解決されました。しかし、コードはまだ機能しません。load()
エクステンションで実行がメソッドに到達していないことがわかりました。この回答のコメントから、あなたのクラスは の子孫でNSObject
ある必要があることを学びました。ですから、なぜこれがまだ機能していないのかわかりません。もう 1 つのオプションは追加ですが、Swift では拡張機能に追加することはできません。以下は、更新されたコードです。UINavigationBar
NSObject
NSObjectProtocol
@objc
問題はまだ未解決です。
import Foundation
import UIKit
let FixedNavigationBarSize = "FixedNavigationBarSize";
extension UINavigationBar {
var fixedHeightWhenStatusBarHidden: Bool {
get {
return objc_getAssociatedObject(self, FixedNavigationBarSize).boolValue
}
set(newValue) {
objc_setAssociatedObject(self, FixedNavigationBarSize, NSNumber(bool: newValue), UInt(OBJC_ASSOCIATION_RETAIN))
}
}
func sizeThatFits_FixedHeightWhenStatusBarHidden(size: CGSize) -> CGSize {
if UIApplication.sharedApplication().statusBarHidden && fixedHeightWhenStatusBarHidden {
let newSize = CGSizeMake(self.frame.size.width, 64)
return newSize
} else {
return sizeThatFits_FixedHeightWhenStatusBarHidden(size)
}
}
override public class func load() {
method_exchangeImplementations(class_getInstanceMethod(self, "sizeThatFits:"), class_getInstanceMethod(self, "sizeThatFits_FixedHeightWhenStatusBarHidden:"))
}
}
更新 2: Jasper は目的の機能を実現するのに役立ちましたが、明らかにいくつかの大きな欠点があります。
load()
ジャスパーが示唆したように、拡張機能のメソッドが起動していなかったため、次のコード ブロックをアプリ デリゲートのdidFinishLaunchingWithOptions
メソッドに移動しました。
method_exchangeImplementations(class_getInstanceMethod(UINavigationBar.classForCoder(), "sizeThatFits:"), class_getInstanceMethod(UINavigationBar.classForCoder(), "sizeThatFits_FixedHeightWhenStatusBarHidden:"))
また、プロパティのゲッターで戻り値を「true」にハードコーディングするfixedHeightWhenStatusBarHidden
必要がありました。アプリのデリゲートでスウィズリング コードが実行されるようになったため、View Controller から値を設定することはできません。これにより、再利用性に関しては拡張機能が冗長になります。
したがって、問題はまだ多かれ少なかれ未解決です。誰かがそれを改善するアイデアを持っているなら、答えてください。