Swiftで関数を実装しようとしているときに、特定の関数パラメータで型推論が破られたような問題が発生しました。他の言語のメモを取って、Swiftには、オブジェクトと、前のオブジェクトと同じ型の別のオブジェクトを返すブロックという2つのパラメータを使用する関数を実装したかったのです。私はそうのようにそれを実装開始しました:それは私が決めたprepare(for:sender:)
プロトコル拡張が自己によって制約された汎用クロージャで誤って推定されるタイプ
セグエ機能に苦しんでいるように見えたとして
func prepare<T>(_ object: T?, with block: ((T?) -> T?)) -> T? {
return block(object)
}
UITableViewController
クラスの内部を使用しようとした後、私は、命名の問題を経験しましたこれを解決するために名前を変更するだけです(別の質問のために上記を保存します)。
func bootstrap<T>(_ object: T?, with block: ((T?) -> T?)) -> T? {
return block(object)
}
この名前は今のところできます。だから私はbootstrap(_:with:)
オブジェクトとクロージャを取る関数を持って、オブジェクトの引数と同じ型のオブジェクトを返します。私は、例えばInt
、特定のオブジェクトでこれを簡単に呼び出すことができます。もちろん
bootstrap(1, with: { $0 + 1 }) // returns 2
しかしこれは、関数がためにそこにあるものではありません。
class ContactDetailHeaderView: UIView, Nibbable {
var user: User?
}
これはNibbable
プロトコル以下のプロトコル拡張機能を使用して、ペン先からフェッチされる:だから、私は、単一の部材により小さなUIView
由来のクラスを持って、その実際の意図する用途にそれを使用し
extension Nibbable where Self: UIResponder {
static func getRoot(withOwner owner: Any, options: [AnyHashable:Any]? = nil) -> Self? {
return self.nib.instantiate(withOwner: owner, options: options).first as? Self
}
}
は、我々はnib
からオブジェクト(このクラスのための私達のUINib
オブジェクト)を取得し、この場合にはContactDetailHeaderView
あるSelf
として、それをキャストすることができます。次に、以前に宣言した関数を使用してオブジェクトを設定することができます。私たちは、私はこの質問の目的のために凝縮しUITableViewController
由来クラスContactDetailTableViewController
のこの内部ん:
class ContactDetailTableViewController: UITableViewController {
var user: User?
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.backgroundView = bootstrap(ContactDetailHeaderView.getRoot(withOwner: self), with: { $0?.user = self.user })
}
}
はしかし、我々は、この関数を呼び出すのエラーが表示されます。
Value of type 'UIView' has no member 'user'
これは予想外です。私たちのgetRoot(withOwner:options:)
関数はSelf
、つまりContactDetailHeaderView
を返します。
はのは、名前付きパラメータと明示的に定義されたタイプで速記の引数を置き換えることにより、型推論を拡張してみましょう:
bootstrap(ContactDetailHeaderView.getRoot(withOwner: self),
with: { (header: ContactDetailHeaderView?) -> ContactDetailHeaderView? in
header?.user = self.user
}
)
確かに私たちのオブジェクトは今UIView
と解釈できるという方法はありませんか?さて、同じエラーが表示されます:
Value of type 'UIView' has no member 'user'
なぜこのようなことが起こりますか? Xcodeでオートコンプリートをチェックしても、header
引数は有効なアクセス可能なプロパティとしてuser
のメンバーを示します。そして、なぜそれがbootstrap(_:with:)
クロージャ内では機能しません
ContactDetailHederView.getRoot(withOwner: self)?.user = self.user
:getRoot(withOwner:options:)
機能を使用すると、他の場所で期待される結果を生成しますか?これはバグですか?私は行方不明の何か他にありますか?
ご協力いただければ幸いです。
私はgistに十分なコードを添付して、問題を再生場所に再現します。簡単にするため、私は
(例えば、標準ライブラリで提供されていますString
に内部オブジェクトであるUser
からuser
タイプを変更)より管理しやすい何かで不要なビットの一部を置き換えますこの質問ことに注意してください。機能が何であるか、またはそれがなぜそれを行うのかについてはではなく、です。同じものを実装する方法はたくさんありますが、その多くははるかに優れています。私はこの関数を現在の形式で使用するかどうかにかかわらず、このコンパイラエラーを解決したいと思います。
まあコンパイラは、自己が純粋 'UIView'サブクラスであることを考えているようです。私が間違って読んでいない限り、2番目から最後のコードスニペットでは、自分自身がどのクラスを参照しているかを指定しません。 'self'とは何か?' bootstrap'メソッドを実装するクラスに存在するユーザパラメータですか?ばかげた質問のように思えるかもしれませんが、あなたは 'header'と' ContactDetailHeaderView'クラスと、ユーザパラメータを要求する 'self'ポインタを持っています。 2つのうちの最初のものがありますので、私はあなたが何かを見落としている可能性があることを賭けています.. – murphguy
右、私はここにコンテキストを含める必要があります。 @murphguy質問を編集させてください –
今あなたの要点を見て心配しないでください – murphguy