Perilaku SwiftUI .frame (tinggi: nil)
Masalah
Saya mendapatkan masalah utas yang mengatakan "Dimensi bingkai tidak valid (negatif atau tidak terbatas)."
Ini kode saya:
struct CellStyle: ViewModifier {
func body (content: Content) -> beberapa Tampilan {
kandungan
.frame (width: .infinity, height: 56, alignment: .center)
.padding (.horizontal, 16)
}
}
Kode berjalan dengan baik, dan saya tampaknya melakukan apa yang seharusnya, jadi saya bingung mengapa itu memberi saya masalah utas. Mengapa kode akan berjalan tanpa lebar / tinggi yang terbatas, bertentangan dengan dokumen Apple? (lihat bagian "Beberapa bacaan" di bawah)
Cara mengatasinya
Kode ini memperbaiki masalah dengan baik, tetapi saya masih berharap saya mengerti mengapa kode sebelumnya tidak macet atau membuat kesalahan.
struct CellStyle: ViewModifier {
func body (content: Content) -> beberapa Tampilan {
kandungan
.frame (tinggi: 56, alignment: .center)
.frame (maxWidth: .infinity)
.padding (.horizontal, 16)
}
}
Sejauh yang saya tahu, ini memberi saya masalah utas karena saya katakan .frame, bahwa saya menginginkan lebar yang tidak terbatas dan menginginkan lebar yang terbatas.
Pertanyaan lain tentang stack overflow
Saya menemukan dua pertanyaan yang menanyakan hal yang sama:
iOS 14 Dimensi bingkai tidak valid (negatif atau tidak terbatas)
SwiftUI iOS14 GeometryReader Dimensi bingkai tidak valid
Dalam pertanyaan pertama, masalah utas masuk akal karena kode yang diberikan .frame(width: p.size.width - padding)tidak ada jaminan yang p.size.widthakan kurang dari padding. Sejauh yang saya tahu, ini adalah masalah di mana nilai yang diberikan bisa negatif.
Masalah ini saya harus lakukan dengan nilai yang diberikan tidak terbatas, jadi pertanyaannya tidak berhubungan.
Pertanyaan kedua masih belum terjawab dan agak kabur, jadi tidak terlalu membantu untuk saya saat ini. Mungkin nanti seseorang akan menjawab dengan jawaban yang membantu, tetapi untuk saat ini, itu belum membantu.
Beberapa bacaan
Melihat dokumen Apple saya menemukan ini:
Gunakan metode ini untuk menentukan ukuran tetap untuk lebar, tinggi tampilan, atau keduanya. Jika Anda hanya menentukan salah satu dimensi, tampilan yang dihasilkan mengasumsikan perilaku ukuran tampilan ini di dimensi lain.
Jadi mengapa itu .frame(width: .infinity, height: 56, alignment: .center)bahkan berjalan sama sekali?
Apa yang dimaksud Apple dengan "tampilan yang dihasilkan mengasumsikan perilaku ukuran tampilan ini di dimensi lain"? Apakah akan selalu menganggap view tersebut sebagai view "push out", sehingga memberikan hasil yang sama .infinity?
Saya menguji ini dan menjalankan kode ini:
struct CellStyle: ViewModifier {
func body (content: Content) -> beberapa Tampilan {
kandungan
.frame (tinggi: 56, alignment: .center)
.padding (.horizontal, 16)
}
}
Tampaknya memberikan hasil yang sama, jadi sekarang saya penasaran apakah pernah ada kasus di mana cepat "mengasumsikan" lebar akan menghasilkan perilaku selain .infinity?
Pertanyaan terakhir
Apa perbedaan perilaku antara .frame(width: .infinity)vs .frame(width: nil)(setara dengan memancarkan lebar atau tinggi).
func frame (lebar: CGFloat? = nil, tinggi: CGFloat? = nil, alignment: Alignment = .center) -> beberapa View
Dokumen Apple
Terima kasih untuk bantuannya!
Jawaban
Karena itu adalah kontrak antarmuka yang didokumentasikan:
/// - Parameters:
/// - width: A fixed width for the resulting view. If `width` is `nil`,
/// the resulting view assumes this view's sizing behavior.
/// - height: A fixed height for the resulting view. If `height` is `nil`,
/// the resulting view assumes this view's sizing behavior.
/// - alignment: The alignment of this view inside the resulting view.
/// `alignment` applies if this view is smaller than the size given by
/// the resulting frame.
///
/// - Returns: A view with fixed dimensions of `width` and `height`, for the
/// parameters that are non-`nil`.
@inlinable public func frame(width: CGFloat? = nil, height: CGFloat? = nil, alignment: Alignment = .center) -> some View
sedangkan tipe pengubah dengan argumen min / max memungkinkan batasan fleksibel (tidak disalin di sini - baca dalam modul SwiftUI yang dihasilkan).
Apa yang dilakukan .frame (width: nil)
Pada dasarnya .frame akan mengambil nilai yang diberikan dan mengembalikan tampilan lain yang diperbarui dengan nilai yang Anda masukkan.
Jika Anda menghilangkan salah satu parameter atau menyetelnya ke nihil, maka ini akan mengambil nilai lebar / tinggi masing-masing dari tampilan sebelumnya.
Kode tes:
struct ContentView: View {
@State var keyValue = ""
var body: some View {
VStack(spacing: 10) {
Text("Something")
.background(Color.blue)
Text("Something")
.frame(width: 300, height: nil, alignment: .center)
.background(Color.blue)
Text("Something")
.frame(width: nil, height: 200, alignment: .center)
.background(Color.blue)
Text("Something")
.frame(width: nil, height: nil, alignment: .center)
.background(Color.blue)
}
}
}
Mengapa .frame (width: .infinity) masih berjalan
.infinity( Apple doc on .infinity ) adalah tipe Float, jadi tidak ada cara untuk .frametidak kecuali, tapi masih bisa menimbulkan masalah. (Jadi masalah utas)
Terima kasih kepada Mark Moeykens atas bantuannya untuk mengantarkan saya ke jawaban ini!