WARNING: Application performed a reentrant operation in its NSTableView delegate. This warning will become an assert in the future.

Can anyone help to understand what is causing this warning message on this SampleCode.

  1. it happens when data in table gets updated
  2. it happens when I have lot of items in table and search for lets say # 6543 and then clear the search.

"WARNING: Application performed a reentrant operation in its NSTableView delegate. This warning will become an assert in the future."

If there are just few items in table, the warning is not there.

And it started when updated to Xcode Version 14 and upward

import SwiftUI

import Foundation



@main

struct TestProjectSWIFTApp: App {

    @StateObject var mydata: MyData = MyData()

    var body: some Scene {

        WindowGroup {

            ContentView()

                .environmentObject(mydata)

        }

        

    }

}



struct ContentView: View {

    @EnvironmentObject var mydata: MyData

    var body: some View {

        NavigationView{

            NavigationLink("TABLE",  destination: MyTable())

            

        }

    }

}



struct User: Identifiable {

    let id: UUID = UUID()

    var name: String

    var score: Int

}





struct MyTable: View {

    @EnvironmentObject var mydata: MyData

    @State private var sortOrder = [KeyPathComparator(\User.name)]

    @State var searchText: String = ""

    var searchResults : [User] {

        if searchText.isEmpty {

            return mydata.alldata

        } else {

            return mydata.alldata.filter{$0.name.localizedCaseInsensitiveContains(searchText)}

        }

    }

    

    var body: some View {

        

        Button("Generate new data", action: {

            mydata.updateTable()

        })

        

        Table(searchResults, sortOrder: $sortOrder) {

            TableColumn("Score"){

                Text("\(Double($0.score))")

            }

            TableColumn("user", value: \.name)

        }

        .onChange(of: sortOrder) {

            mydata.alldata.sort(using: $0)

        }

        .searchable(text: $searchText)

    }

}







@MainActor class MyData : ObservableObject{

    @Published var alldata: [User] = []

    



    

    init(){

        self.setData()

    }

    

    func setData(){

        alldata = [

            User(name: "User 1", score: 95),

            User(name: "User 2", score: 80),

            User(name: "User 3", score: 85)

        ]

    }

    

    func updateTable(){

        var newallData: [User] = []

        var x = 0

        while x < 10000{

            newallData.append(User(name: "User #\(x)", score:  Int.random(in: 10..<999999)))

            

            x = x + 1

        }

        alldata = newallData

    }

    

}
Post not yet marked as solved Up vote post of Rauli Down vote post of Rauli
2.8k views
  • I am getting this too when clearing the search field for a table in a macOS app built with SwiftUI.

    My code is very similar to the OP's code. I have a MainActor class that is an @ObservableObject (I create a singleton of it) holding a Deque of data that is @Published. I have a computed property that returns a filtered Deque (from the published Deque), and that what is used to populate the table. The table has a .searchable(text:) modifier.

    I get the alert when I clear the search field.

Add a Comment

Replies

I don't get any errors. I'm using Xcode version 14.1 (14B47b) and I'm deploying to a physical iPhone 14 Pro Max and the same as a Simulator.

What are your exact steps to reproduce it? Are you typing something in then seeing the error, or typing something in and backspacing to delete the text you entered and then you see an error?

  • I run it locally on Mac. 1.I run the app 2.press button to generate data 3.during the table refresh the warning is shown 4. now once I have thousands items in table you type to search some number 5. table shows the filtered line 6 now clear the search criteria from this little x 7 and warning shows again

Add a Comment

So you're running it as a Mac app?

And your EXACT steps are then:

  1. Run the app.
  2. Press the "TABLE" link.
  3. Press the "Generate new data" button. This is when you see the error?
  4. Now that there are 1,000s of items you type what exactly? "User #1234" or "#1234" or "1234"?
  5. Clear the search criteria, how? Do you press the little X button in the text field, or do you select the text and press the delete key, or do you tap at the end of the text and press backspace until the text is gone? These are three completely different ways of clearing the text, and they call three different methods on the text field.

It's extremely important to give the exact steps to reproduce an issue, or we can't really help because we can't reproduce it because we aren't doing the same thing as you.

No matter what I do I do not get the error.

Yes I run it as macOS app.

Run the app. YES Press the "TABLE" link. YES Press the "Generate new data" button. This is when you see the error? YES

The message is related to table refresh. If you don't see it then probably there are not enough items in table. So pls keep increasing the rows. instead of while x < 10000 try to increase it to 100 000 000. Different hardware acts differently. less powerful hardware needs less items in table for message to appear.

But even then my concern is about architecture. is there something obviously wrong in the code, how the table items are refreshed/renewed?

Okay, well I've tried with 100,000 rows and I still don't get the error (Mac Studio M1 Max, 10c/24c, 64GB RAM), but it takes ages to generate the new data.

I cannot see any situation where you would want to have 100,000 (or even just 1,000) rows in a table view, so I think you should probably re-architect what you're trying to do here. Maybe use pagination so you only show 100 rows at a time, but let your search function on the full dataset?

I have the same problem with a mac swiftui app that uses a table view compiled with Xcode 14.1. The error happens when you have more data that can fit into the table view. The warning occurs when you use computed properties for sorting like this:

private var tableData: [SomeStruct] { fetchRequestData .sorted(using: sortOrder) }

or you filter data:

private var tableData: [SomeStrict] { fetchRequestData .filter { $0.localizedCaseInsensitiveContains(searchText) } }

When all data(rows) fits on the screen there is no warning!

The error happens to me too and I have way less data now (4 rows). I have an M1 mac with 32 GB ram.

I've managed to get this warning once in my own SwiftUI macOS application when adding a single record to core data. However, I wasn't able to replicate it again, which makes it very difficult to debug and find the exact cause. Based on the warning "reentrant operation", I'm guessing it's related to concurrency and possibly a background thread trying to update the UI or some sort of race condition.

If you can replicate this consistently, perhaps do a test by running the core data operation on the main actor, then we'll know for certain what's the cause.

I'm getting this warning on an Obj-C Mac App using an NSOutlineView. This not specific to SwiftUI.

This appears to happen when I ask the outline view to load several "parent" rows that are not visible (they extend below the visible rect). Hence, this only happens when I load a certain number of rows (or more), be it with -reloadData or -insertItemsAtIndexes:inParent:withAnimation:.

The total height of the rows that are loaded appears to be a factor, since I get this waning when I load fewer rows if rows are taller. It may happen with only 5 rows.

It seems I only get the warning if the rows that are loaded have child rows (i.e., they represent parent items with children). When I load only "child" rows (with -insertItemsAtIndexes:inParent:withAnimation: and inParent is not nil), I don't get this warning, even if I load many, many children.

I don't like this. I didn't get the warning before I update to Ventura/Xcode 14.2.

I'm experiencing the same warning when using a NSOutlineView without SwiftUI, but only a few rows. I opened a new topic here.

I'm using NSTableViewDiffableDataSource and as soon as I import a bunch of records (not even that many - like 600), I get the error if I have animations turned on.

[self.tableDiffableDataSource applySnapshot:snapshot animatingDifferences:YES completion:^{

}];

But as soon as I turn OFF animatingDifferences, I no longer get the error.

I see the same message with a MacOS app where I add entries into an array that is @Published from a class and in place sort the array after the append. The array is bound to swiftui List. The message comes up randomly when adding rows to the array (via a button click). If I comment out the sort, then the warning does not appear.

At a guess for me, appending to the array causes and objectWillChange, the sort similarly generates an objectWillChange and some sort of race condition is happening under the covers in which the append, sort and gui updates, probably running on different threads, are tripping over each other ?? Something like before the gui has finished updating, the underlying data is changing. Looks like a compiler issue that we have to hope is fixed BEFORE it becomes an assert that crashes apps....

I am getting this too when clearing the search field for a table in a macOS app built with SwiftUI.

My code is very similar to the OP's code. I have a MainActor class that is an @ObservableObject (I create a singleton of it) holding a Deque of data that is @Published. I have a computed property that returns a filtered Deque (from the published Deque), and that what is used to populate the table. The table has a .searchable(text:) modifier.

I get the alert when I clear the search field.

  • try changing the list's ID at same time

Add a Comment

FYI: I just compiled and ran Apple's sample GardenApp from their 2021 WWDC presentation SwiftUI on the Mac: Build the fundamentals, and after entering a search term for the table and then clearing the search term, the app generates the same warning. So, at least we are in good company.

2023-04-11 07:27:38.870357-0700 Garden App[14053:1032028] WARNING: Application performed a reentrant operation in its NSTableView delegate. This warning will become an assert in the future.

Having the same problem, anyone has anything new to help solve the issue?

I have a NavigationSplitView with three columns and a .searchable()on the first column List view. Data to the views come from Core Data @FetchRequest. Whenever user removes a character from the search field or clears the search field, the same warning is displayed. When entering search text, warning does not appear.

This does not happen always. For example when I enter a search text resulting in one row, and then remove one letter from search text. Then three rows are displayed and this warning does not appear. After removing another letter, resulting to five rows appearing, then this warning appears.

Relevant parts of code below.

struct ContentView: View {
	@Environment(\.managedObjectContext) var moc
	@FetchRequest (sortDescriptors: [SortDescriptor(\.subject)]) private var categories: FetchedResults<Category>

	@State private var selectedCategory : Category? = nil
	@State private var selectedTerm: Term? = nil

	@State private var searchText = ""

	var body: some View {
		NavigationSplitView {
			List(selection: $selectedCategory) {
				ForEach(categories, id: \.self) { category in
					CategoryRowView(category: category)
						.swipeActions(edge: .trailing) {
							Button(role: .destructive) {
								toDeleteCategory = category
								showDeleteCategoryConfirmation.toggle()
							} label: {
								Label("Delete", systemImage: "trash")
							}
						}
				}
			}
			.listStyle(.sidebar)
			.searchable(text: $searchText)
...
		} content: {
			if let category = selectedCategory {
				List(category.viewTerms(filter: searchText.isEmpty ? nil : searchText), id: \.self, selection: $selectedTerm) { term in

and the implementation of category.viewTerms(filter: ) that does the filtering based on searchText (Category is a Core Data class):

extension Category {
...
	func viewTerms(filter: String?) -> [Term] {
		var terms = viewTerms
		if filter != nil {
			terms = terms.filter( { $0.termSearchText.localizedCaseInsensitiveContains(filter!) } )
		}
		return terms
	}
	
	var viewTerms: [Term] {
		let terms = categoryTerms?.allObjects as? [Term] ?? []

		return terms.sorted(by: {$0.viewPrimaryName < $1.viewPrimaryName } )
	}

Where the Category.categoryTerms is a one-to-many Core Data relationship from Category entity to Term entity.

I no longer see this warning posted on the console after updating to Xcode 15. I'm still using Ventura.