Xcode: Type of expression is ambiguous without more context ERROR in UISlider
The error message and position is misleading, the problem is in the mixing of types in this line:
self.scrollView.frame.origin.y = CGFloat(imageView.image?.size.height ?? 0 * getValue)
Convert getValue
to CGFloat
to resolve this:
self.scrollView.frame.origin.y = imageView.image?.size.height ?? 0 * CGFloat(getValue)
Type of expression is ambiguous without more context in `ForEach` over array of custom class
It seems like you didn't conform to ExpensePeriod
in ExpenseYear
you are missing start
and end
variables (most likely it's the source of error, but it's hard to tell)
After conforming, if the error persists I would replace in the loop the MonthlyListView
view with Text
and I would keep replacing stuff until I find the source of the error.
This error usually occurs when you are missing a keyword or formatting a loop. Most of the time it just means the compiler can't interpret what you wrote.
I would solve the issue but the code above is missing stuff to be able to run it just by copying and pasting it.
EDIT:
So your issue lies in the forEach
because if you pay close attention, your code look like this ForEach(ExpenseYear.array(from: expenses.last!, to: expenses.first!))
however, expenses is defined as follows var expenses: FetchedResults<Expense>
where each item from this array will be of type Expense
in your ExpenseYear
array your header looks like this tatic func array(from startDate: Date, to endDate: Date) -> [ExpenseYear]
which the first and 2nd parameter are of type Date
yet you are passing them an item of type Expense
. expenses.last!
returns a Expense
object and that's not a Date
! so to solve the issue you would first have to do something like this expenses.last!.datetime!
So changing your code to this
ForEach(ExpenseYear.array(from: expenses.last!.datetime!, to: expenses.first!.datetime!), id: \.id) { expense in
should solve your problem. Keep in mind the following
Change this code to reflect everywhere in your app, I only changed it in 1 single instance as I have commented out the rest of your code.
Force unwrapping is always a bad idea, so I would suggest you handle dates correctly but guard unwrapping them first.
Also, I know you commented that I didn't need to implement start
and end
in ExpenseYear
but unfortunately, I wasn't able to compile without implementing them so I had to.
Alternatively, you can change the .array
protocol to take in an Expense
instead of Date
and then you handle how to return an array from the object Expense
so your protocol would look something like this
static func array(from startExpense: Expense, to endExpense: Expense) -> [Period]
and implementation can be something like this
static func array(from startExpense: Expense, to endExpense: Expense) -> [ExpenseYear] {
guard let startDate = startExpense.datetime, let endDate = endExpense.datetime else {
return []
}
return array(of: .year, from: startDate, to: endDate)
}
where you have already taken care of guarding against nil dates and you don't have to change anything except implementation (I honestly would prefer this method)
I know to implement the second method you would have to change how you set your protocol and bunch of other stuff, so what you can do is instead pass an optional Date
to your array
, something like this static func array(from startExpense: Date?, to endExpense: Date?) -> [Period]
and then guard unwrap them else return empty array. But you still have the issue of unwrapping .last
and .first
expense in your ForEach
loop.
Good luck with the rest!
Swift 4: Type of expression is ambiguous without more context inside loop
Swift errors are not very helpful. The problem there is that split method returns an array of substrings:
func split(separator: Character, maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true) -> [Substring]
And the Data initializer expects a String:
init?(base64Encoded base64String: String, options: Data.Base64DecodingOptions = [])
You just need to initialize a new string from your substring:
if let photos = b64fullstring?.split(separator: ";") {
for pic in photos {
if let decodedData = Data(base64Encoded: String(pic), options: .ignoreUnknownCharacters) {
if let decodedString = String(data: decodedData, encoding: .utf8) {
print(pic)
}
}
}
}
Another option is to use components(separatedBy:)
method which returns an array of strings instead of substrings:
func components<T>(separatedBy separator: T) -> [String] where T : StringProtocol
if let photos = b64fullstring?.components(separatedBy: ";") {
for pic in photos {
if let decodedData = Data(base64Encoded: pic, options: .ignoreUnknownCharacters) {
if let decodedString = String(data: decodedData, encoding: .utf8) {
print(pic)
}
}
}
}
SwiftUI Xcode 11 beta 5 / 6: Type of expression is ambiguous without more context
After your update in your answer, I see some changes needed:
- Use
ObservableObject
(no need to useCombine.ObservableObject
) - Missing function
scanPassport
, I added a bogus one. willChange
no longer exists, it is nowobjectWillChange
. And it is autosynthesize for you.
import SwiftUI
class ClPassport : ObservableObject , Identifiable {
@Published var mrz : String = "" //{ didSet { update() } }
var isValid : Bool {
return true
}
func update() {
objectWillChange.send()
}
func getMRZKey() -> String {
return ""
}
}
struct ContentView : View {
@ObservedObject var passportDetails = ClPassport()
var body: some View {
ZStack{
VStack(alignment: .leading){
HStack{
Spacer()
Button(action: {
self.scanPassport( mrzKey: self.passportDetails.getMRZKey() )
}) {
Text("Read Chip")
.font(.largeTitle)
.foregroundColor(passportDetails.isValid ? .primary : Color.secondary.opacity(0.25))
.padding()
}.padding()
.background(Color.white.opacity(passportDetails.isValid ? 1 : 0.5))
.cornerRadius(15)
.padding()
.disabled( !passportDetails.isValid )
Spacer()
}
TextField("MRZ", text: $passportDetails.mrz)
}
}
}
func scanPassport( mrzKey: String ) {
//do stuff with mrzKey
}
}
Type of expression is ambiguous without more context error SwiftUI
I highly suggest to separate the View and the logic of the View. A common approach is the MVVM concept. I've incorporated this concept in the following example (tested with Xcode 11.3.1):
import SwiftUI
import Combine
final class ContentViewModel: ObservableObject {
@Published var darkModeActivated: Bool
@Published var backgroundColor: Color
private var sink: AnyCancellable?
init() {
self.darkModeActivated = false
self.backgroundColor = Color.white
self.sink = self.$darkModeActivated.sink() { value in
if value {
self.backgroundColor = Color.black
} else {
self.backgroundColor = Color.white
}
}
}
public func toggleDarkmode() {
self.darkModeActivated.toggle()
}
}
struct ContentView: View {
@ObservedObject var viewModel: ContentViewModel
var body: some View {
ZStack {
VStack {
Text("Neumorphism")
.font(.system(size: 32,
weight: .bold,
design: .rounded))
.padding(20)
Button("Hello world", action: { self.viewModel.toggleDarkmode() })
.padding(20)
Button("Hello world2", action: { self.viewModel.darkModeActivated.toggle() })
.padding(20)
}
.frame(minWidth: 0, maxWidth: .infinity,
minHeight: 0, maxHeight: .infinity,
alignment: .center)
.background(self.viewModel.backgroundColor)
.edgesIgnoringSafeArea(.all)
Toggle(isOn: self.$viewModel.darkModeActivated) {
Text("Dark Mode")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(viewModel: .init())
.environment(\.colorScheme, .light)
}
}
In the example the View binds directly against the variables darkModeActivated
to set the state of the toggle button and backgroundColor
to store the color of the background. Simply spoken, you use the $
prefix in self.$viewModel.darkModeActivated
if you change the value of the variable from within the view. A comprehensive explanation can be found here. The logic what happens if the state changes is fully handled by the ViewModel.
The toughest part in the example above was clearly to get notified when the value of darkModeActivated
changes. Therefore, I've used the Combine framework to attach a subscriber, as proposed here.
Using a normal button to activate the dark mode also pretty easy. Just call a ViewModel function from within the button's action closure. Or directly toggle the value like in the example above.
Getting Type of expression is ambiguous without context when using list inside of VStack
Problem is here
List(viewModel.taks)
Make sure your custom model conforms to
struct Task:Identifiable {
or add id property
List(viewModel.taks, id: \.id) { item in
Related Topics
Suppress Warnings from Dependencies with Swift Package Manager
Unwrapping Optional in Swiftui View
Closure:Use Unresolved Identifier 'Self'
How Would I Create a Constant That Could Be One of Several Strings Depending on Conditions
Generic Within a Generic in Swift
Google Sign-In via Firebase: Gidsignindelegate Does Not Conform to Viewcontroller
Swiftui View and Uihostingcontroller in Uiscrollview Breaks Scrolling
How to Prevent Multiple Instances of the Same Window from Opening in MACos
Swift Protocol as Generic Parameter
Provide Simple Method to Get Current Speed (Implementing Speedometer)
How to Trigger Xcode's 'Update to Latest Package Versions' from Command Line
Mandatory Init Override in Swift Uinavigationcontroller Subclass
Create a Navigationlink Without Back Button Swiftui
Swift- How to Display Image Over Button
Why Specializing a Generic Function Explicitly Is Not Allowed