Search code examples
core-dataswiftuiswiftui-list

CoreData FetchRequest is loading my List with Optional result data in addition to the FetchedData


I'm calling a @FetchRequest inside of the AdminView struct, where I wish to present the data inside of a List using a ForEach. I'm Requesting all User entity data but when I run the app, the list shows my 2 existing entry results but it also shows about 40 entries that default to the Optional String "TEST" for some reason.

I'm trying to understand how I can get the List to only show the two User Entries without showing the default String in the list.

Much appreciated!

Here is the relevant code:

import Foundation
import CoreData


extension User {

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

    @NSManaged public var admin: Bool
    @NSManaged public var company: String?
    @NSManaged public var name: String?
    @NSManaged public var password: String?
    @NSManaged public var photo: Data?
    @NSManaged public var username: String?
    @NSManaged public var id: UUID?
    @NSManaged public var tickets: NSSet?

}

// MARK: Generated accessors for tickets
extension User {

    @objc(addTicketsObject:)
    @NSManaged public func addToTickets(_ value: Ticket)

    @objc(removeTicketsObject:)
    @NSManaged public func removeFromTickets(_ value: Ticket)

    @objc(addTickets:)
    @NSManaged public func addToTickets(_ values: NSSet)

    @objc(removeTickets:)
    @NSManaged public func removeFromTickets(_ values: NSSet)

}

extension User : Identifiable {

}

extension User {
    static func getAllUsers() -> NSFetchRequest<User> {
        let request:NSFetchRequest<User> = User.fetchRequest()

        let sortDescriptor = NSSortDescriptor(keyPath: \User.company, ascending: false)
        request.sortDescriptors = [sortDescriptor]

        return request
    }
}





import SwiftUI

struct AdminView: View {
    @Environment(\.managedObjectContext) var moc
    @EnvironmentObject var goToContentView: moveToContentView
    @ObservedObject var selectedUser : User
    @State var selectedImageArray : [UIImage]
    
    @FetchRequest(fetchRequest: User.getAllUsers()) var allUsers:FetchedResults<User>

    var body: some View {
        List{
            ForEach(self.allUsers) { user in
                VStack{
                    Text(user.company ?? "TEST")
                }
            }
     }
        .toolbar(content: {
            EditButton()
        })
        .animation(.default)
        .navigationBarBackButtonHidden(true)
        .navigationTitle("ADMIN")
        .navigationBarItems(leading: Button(action: {
            
            if self.goToContentView.goToViewFromLogin == true {
                self.goToContentView.goToViewFromLogin = false
            } else {
                self.goToContentView.goToViewFromRegister = false
            }
            
        }) {
            HStack {
                Text("Sign Out")
            }
        },trailing: HStack{
            Image(systemName: "bell")
                .font(.system(size: 30))
            Image(uiImage: selectedImageArray.first!)
                .resizable()
                .scaledToFit()
                .clipShape(Circle())
                .frame(width: 50, height: 50)
            Text(selectedUser.name!)
                .font(.system(size: 20))
        })
        
    }
}

Solution

  • Add a filter to the list. You can also use let instead of the nil-coalescing operator. No need for the VStack since the Text will all be inside the list.

    List {
       ForEach(self.allUsers.filter({ $0.company != nil })) { user in
          if let company = user.company {
              Text(company)
          }
       }
    }