Azon Yankee
Azon Yankee

Reputation: 201

Unable to infer complex closure return type; add explicit type to disambiguate Swift UI

I am getting an error saying that the view is "Unable to infer complex closure return type; add explicit type to disambiguate" when I keep my foreach loop in the view. When I take my foreach loop out of the view it works fine. I just started getting this error when I implemented looping over an object before I just looped till a certain number passing in "Dummy Strings" into the ExerciseTableRow view. Not sure how to get around this. Thank you in advance!

struct PassedExerciseCard: View {
    var exercise : String
    var sets : [ExerciseSet]
    
    var body: some View {
        
        VStack{
            Text(exercise).font(.title).padding(.bottom, 5)
            Group{
                HStack{
                    Group{
                        Text("Set")
                        Text("Weight")
                        Text("Reps")
                    }.padding(.horizontal, 30)
                    .offset(x: -15, y: -5)
                    
                }
                VStack{
                    ForEach(sets, id: \.self){ (set : ExerciseSet) in
                        ExerciseTableRow(set: set.set, readOnly: true, setWeight: set.weight, setReps: set.reps)
                    }
                }.padding(.bottom, 5)
            }.offset(x: 20, y: 0)
            
            
        }
        .padding()
        .background(Color.offWhite)
        .cornerRadius(20)
        .shadow(color: Color.black.opacity(0.2), radius: 10, x:10, y:10)
        .shadow(color: Color.white.opacity(0.7), radius: 10, x:-5, y:-5)
        .padding(.vertical)
    }
}

struct PassedExerciseCard_Previews: PreviewProvider {
    
    static var exercise :[ExerciseSet] = []
    
    static var previews: some View {
        PassedExerciseCard(exercise: "Bench", sets: exercise)
    }
}

UPDATE

I learned that the error I am having isn't the error at all. The actual error is that the compiler thinks I don't have properties for the ExerciseSet which is an NSManagedObject. I updated the object to have an idea and updated the foreach loop to use the specific ID for each element as the identifier and still no luck.

Updated Code:

struct PassedExerciseCard: View {
    var exercise : String
    var sets : [ExerciseSet]
    
    var body: some View {
        
        VStack{
            Text(exercise).font(.title).padding(.bottom, 5)
            Group{
                HStack{
                    Group{
                        Text("Set")
                        Text("Weight")
                        Text("Reps")
                    }.padding(.horizontal, 30)
                    .offset(x: -15, y: -5)
                    
                }
                VStack{
                    ForEach(sets, id: \.exerciseSetId){ set in
                        ExerciseTableRow(set: set.set, readOnly: true, setWeight: set.weight, setReps: set.reps)
                    }
                }.padding(.bottom, 5)
            }.offset(x: 20, y: 0)
            
            
        }
        .padding()
        .background(Color.offWhite)
        .cornerRadius(20)
        .shadow(color: Color.black.opacity(0.2), radius: 10, x:10, y:10)
        .shadow(color: Color.white.opacity(0.7), radius: 10, x:-5, y:-5)
        .padding(.vertical)
    }
}

NSManagedObject Entity:

import Foundation
import CoreData


extension ExerciseSet {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<ExerciseSet> {
        return NSFetchRequest<ExerciseSet>(entityName: "ExerciseSet")
    }

    @NSManaged public var reps: Int16
    @NSManaged public var set: Int16
    @NSManaged public var weight: Int16
    @NSManaged public var exerciseSetId: UUID?
    @NSManaged public var origin: Exercise?

}

Also Exercise set has a one to one relationship with workout which is:

extension Workout {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Workout> {
        return NSFetchRequest<Workout>(entityName: "Workout")
    }

    @NSManaged public var date: String?
    @NSManaged public var muscle: String?
    @NSManaged public var workoutId: UUID?
    @NSManaged public var exercise: NSSet?
    
    public var wrappedDate: String{
        date ?? "Unknown Date"
    }
    
    public var wrappedMuscle: String {
        muscle ?? "Unknown Muscle"
    }
    
    public var exerciseArray: [Exercise] {
        let set = exercise as? Set<Exercise> ?? []
        
        return set.sorted{
            $0.wrappedName < $1.wrappedName
        }
     }

}

// MARK: Generated accessors for exercise
extension Workout {

    @objc(addExerciseObject:)
    @NSManaged public func addToExercise(_ value: Exercise)

    @objc(removeExerciseObject:)
    @NSManaged public func removeFromExercise(_ value: Exercise)

    @objc(addExercise:)
    @NSManaged public func addToExercise(_ values: NSSet)

    @objc(removeExercise:)
    @NSManaged public func removeFromExercise(_ values: NSSet)

}

In the view that calls the PassedExerciseCard (Where the error is being thrown) I pass in the property on the WorkoutEntity : "exerciseArray" into the sets property that I am using in the foreach loop. I believe this is where the error is occurring

Exercise Table Row:

struct ExerciseTableRow: View {
    @State public var weight : String = "0"
    @State public var reps : String = "0"
    var set : Int
    var readOnly : Bool
    var setWeight : Int
    var setReps : Int
    var body: some View {
        
        HStack{
            Text(String(set))
                .padding(.trailing, 40)
                .padding(.leading, 10)
            if readOnly == false{
                Group{
                    TextField("0", text: $weight)
                    TextField("0", text: $reps)
                }.textFieldStyle(RoundedBorderTextFieldStyle())
                    .frame(width: 50)
                    .multilineTextAlignment(.center)
                    .keyboardType(.numberPad)
                    .padding(.horizontal, 30)
            }
            else{
                Group{
                    Text(String(setWeight))
                    Text(String(setReps))
                }
                .frame(width: 50)
                    .overlay(
                        RoundedRectangle(cornerRadius: 5)
                            .stroke(Color.black, lineWidth: 1)
                    )
                    .padding(.bottom, 5)
                    .padding(.horizontal, 30)
            }
            
        }
        
        
    }
}

Upvotes: 1

Views: 273

Answers (1)

pawello2222
pawello2222

Reputation: 54426

The error occurs because you have a mismatch between data types:

extension ExerciseSet {
    ...
    @NSManaged public var reps: Int16
    @NSManaged public var set: Int16
    @NSManaged public var weight: Int16
    ...
}

but in the ExerciseTableRow they are of type Int:

var set : Int
var setWeight : Int
var setReps : Int

Change them to Int16 and it will work:

var set : Int16
var setWeight : Int16
var setReps : Int16

Upvotes: 1

Related Questions