Error: Initializer 'init(_:)' requires that 'BindingString' conform to 'StringProtocol'
Use the @Published
property wrapper in your Service
class, rather than didChange
, and iterate over the indices of service.items
like so:
struct Item: Identifiable {
var id: String
var label: String
var isOn: Bool {
didSet {
// Added to show that state is being modified
print("\(label) just toggled")
}
}
}
class Service: ObservableObject {
@Published var items: [Item]
init() {
self.items = [
Item(id: "0", label: "Zero", isOn: false),
Item(id: "1", label: "One", isOn: true),
Item(id: "2", label: "Two", isOn: false)
]
}
}
struct MyView: View {
@ObservedObject var service: Service
var body: some View {
List {
ForEach(service.items.indices, id: \.self) { index in
Section(header: Text(self.service.items[index].label)) {
Toggle(isOn: self.$service.items[index].isOn) {
Text("isOn")
}
}
}
}
.listStyle(GroupedListStyle())
}
}
Update: Why use indices?
In this example, we need to get two things from each Item in the model:
- The
String
value of thelabel
property, to use in a Text view. - A
Binding<Bool>
from theisOn
property, to use in a Toggle view.
(See this answer where I explain Binding.)
We could get the label value by iterating over the items directly:
ForEach(service.items) { (item: Item) in
Section(header: Text(item.label)) {
...
}
But the Item struct does not contain a binding. If you tried to reference Toggle(isOn: item.$isOn)
, you'd get an error: "Value of type 'Item' has no member '$isOn'."
Instead, the Binding is provided at the top level by the @ObservedObject property wrapper, meaning the $
has to come before service
. But if we're starting from service
, we'll need an index (and we cannot declare intermediate variables inside the ForEach struct, so we'll have to compute it inline):
ForEach(service.items) { (item: Item) in
Section(header: Text(item.label)) {
Toggle(isOn: self.$service.items[self.service.items.firstIndex(of: item)!].isOn) {
// This computes the index ^--------------------------------------^
Text("isOn")
}
}
}
Oh, and that comparison to find the index would mean Item has to conform to Equatable. And, most importantly, because we are looping over all items in the ForEach, and then again in the .firstIndex(of:), we have transformed our code from O(n) complexity to O(n^2), meaning it will run much more slowly when we have a large number of Items in the array.
So we just use the indices. Just for good measure,
ForEach(service.items.indices, id: \.self) { index in
is equivalent to
ForEach(0..<service.items.count, id: \.self) { index in
Initializer 'init(_:)' requires that 'BindingString' conform to 'StringProtocol' SwiftUI Text
Text
displays an immutable String
, hence it's initialiser takes a String
, not a Binding<String>
.
So inject the String
, not a Binding
to it.
Text(state.resultString)
Moreover, @State
should only be used on View
s. resultString
should be @Published
, not @State
.
@EnvironmentObject Initializer 'init(_:)' requires that 'BindingString' conform to 'StringProtocol'
Text
takes in a String
not a Binding<String>
. Replace the line you pointed out with the following:
Text(storage.buttonTitle)
Initializer 'init(_:)' requires that '' conform to 'StringProtocol' SwiftUI Picker with Firebase
You may try the following:
struct SchoolDetailsView: View {
@ObservedObject var schoolData = getSchoolData() // make `@ObservedObject`/`@StateObject` instead of const array
@State var selectedSchool = "" // `schoolName.id` is of type String
var body: some View {
VStack {
Form {
Section {
Picker(selection: $selectedSchool, label: Text("School Name")) {
ForEach(schoolData.datas, id: \.id) { // choose whether you want to tag by `id` or by `name`
Text($0.name)
}
}
Text("Selected School: \(selectedSchool)")
}
}.navigationBarTitle("Select your school")
}
}
}
Initializer 'init(_:)' requires that 'OneCall.HourlyResponse' conform to 'StringProtocol'
Your weather
instance is of type OneCall
.
When you use weather.hourly
, it is of type OneCall.HourlyResponse
, which is obviously doesn't conform to StringProtocol
.
weather.hourly.hourly
is your string property which you need to use.
requires that 'moveView' conform to 'StringProtocol' in swiftui
Your struct is of type 'View' and you are comparing it to a 'String' constant.
You could check the boolean value:
.opacity(moveView(move: $skc.move).move ? 0.1 : 0.8)
But using the expression:
moveView(move: $skc.move)
does not make sense here. You are creating a new view here with the value of the variable.
Better:
.opacity( skc.move ? 0.1 : 0.8)
Referencing operator function '!=' on 'StringProtocol' requires that 'BindingString' conform to 'StringProtocol' swiftui
you only need the "$" dollar sign if you want to use the binding value, it means you want to change the value of it. In your case just use the the variable without the $.
if viewModel.users[indexValue].relationshipLabel != "Choose" {
ShowView()
} else {
HideView()
}
SwiftUI - Error - Initializer 'init(_:rowContent:)' requires that 'CustomDataModel' conform to 'Identifiable'
Give your type an id and make it identifiable and if you don’t need decidable don’t add it.
struct MyType: Encodable, Identifiable {
let id = UUID()
// other properties
}
Using Codable
is just shorthand for adding Encodable
and Decodable
. So if you don’t need both, then just use the one you need.
Does not conform to String protocol SwiftUI Picker View
As E.Coms noted, the solution is to use one of the following:
Text(self.cardController.cards[$0].description)
Text(String(describing: self.cardController.cards[$0]))
Here's an explanation of why you have to do this inside the Text
initializer, but not print()
.
Look at the two initializers for Text
:
init(verbatim content: String)
(docs)
init<S>(_ content: S) where S : StringProtocol
(docs)
You must pass either a String
or a Substring
, the only two types conforming to StringProtocol
. In this case, even though your type conforms to CustomStringConvertible
, you are still passing a Card
.
Contrast this with something like the print
function:
func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
(docs)
Notice that the print
function's arguments are denoted by Any
, which is explained as
Any can represent an instance of any type at all, including function types.
The print function then converts whatever you passed it to a String
:
The textual representation for each item is the same as that obtained by calling String(item).
String
has an initializer which takes a type conforming to CustomStringConvertible
and returns the description
property.
So the reason you can write print(Card())
and not Text(Card()
is because the print function has an intermediate step through String
that can understand your conformance to CustomStringConvertible
, but Text
does not. If Text
allowed you to pass it any type, it would be both more ambiguous ("What is the text representation of this type?" is not necessarily immediately apparent, as it depends on a hierarchical set of protocols), and more work for the SwiftUI system, which is already doing a lot.
Related Topics
iOS 13 Modals - Calling Swipe Dismissal Programmatically
Swift Get Nsdata of a Video from Photos Library
How to Understand What Is Causing a Crash Involving '_Nstouchbarfinderobservation'
Ios/Tvos Playground Fails with "Unable to Find Execution Service for Selected Run Destination"
Firebase References Undeclared
Weak Method Argument Semantics
Nswindow with Round Corners in Swift
Deleting a Camera Roll Asset Using Photos Framework
Core Data: Rename Attribute Without Having Issues with Users and Their Current Data
Not Getting Expected Delegate Calls When Trying to Restore In-App Purchases with Storekit
Protocol Extension Initializer Forcing to Call Self.Init
Uiprogressview Progress Update Very Slow Within Alamofire (Async) Call
Swift Enumeration Order and Comparison
How to Implement Default Associated Values with Swift Enums
Swift Conditional Conformances with Generic Type
How to Retrieve All Contacts Using Cncontact.Predicateforcontacts