0

I know, this is a very unusual thing to do, but I noticed that SwiftUI view won't update when a @State property is assigned from a pointer:

struct ContentView: View {
    @State private var numbers: [Int32] = []

    var body: some View {
        VStack {
            Text("\(numbers.description)")

            Button(action: {
                self.numbers.append(Int32.random(in: 0..<1000))
            }) {
                Text("Add a random number!")
            }

            Button(action: {
                var pointer: UnsafeMutableBufferPointer<Int32>!
                self.numbers.withUnsafeBufferPointer {
                    pointer = UnsafeMutableBufferPointer(mutating: $0)
                    sortMyArr(pointer.baseAddress!, Int32(self.numbers.count))
                }
                self.numbers = Array(pointer)
            }) {
                Text("Sort!")
            }
        }
    }
}

The sortMyArr is a dumb bubble sort in C:

void sortMyArr(int *arr, const int size)
{
    for (int i = 0; i < size; ++i) {
        for (int j = i; j < size; ++j) {
            if (arr[i] < arr[j]) {
                int tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }
        }
    }
}

The view updates when using self.numbers.sort() or self.numbers = self.numebers.sorted(), but not the way I used above.

As a hack, I can update the view with

    @State private var numbers: [Int32] = [] {
        didSet { self.needsUpdate = true }
    }
    @State private var needsUpdate = false {
        didSet { if self.needsUpdate { self.needsUpdate = false } }
    }

    // body view ...
    .background(Text("\(needsUpdate).description)").hidden())

Is there a way to notice SwiftUI without such a hack? This can be a problem when a project uses a bridge to C/C++.

EDIT: The same happens for NSMutableArray, using

self.someNSArray.sort(using: [NSSortDescriptor(key: "self", ascending: true)])
2
  • It is not updated, because it is not actually changed (ie. sorted), try with local copy var sorted = self.numbers in button action. Commented Apr 27, 2020 at 6:47
  • I realized that NSArray is a reference type, so making a local copy worked. However, it doesn't work for the pointer based approach. It seems that Swift Array is not noticed about its internal state change. I printed out the pointer addresses, and .sort() of Swift Array method indeed modified the begining pointer address, while the manual sort via C did not (which is obvious, because it was sorted in-place using a pointer). I don't think there is a non-hacky way to notify Swift Array about the change. Commented Apr 27, 2020 at 10:42

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.