Xcode 11 Beta 7/Catalina Beta 7 crash with ObservableObject

Since upgrading to Xcode11/Catalina Macos Beta 7, programs that use ObservableObject and @ObservedObject crash with memory access error. The programs worked with previous betas and compile on beta 7. I created a simple macos test program to isolate the problem and only modified the Xcode generated ContentView.swift to be:


import SwiftUI


public class TestClass: ObservableObject {

@Published public var str: String = "Goodbye"

}


struct ContentView: View {

@ObservedObject public var testObject: TestClass

var body: some View {

Text(testObject.str)

.frame(maxWidth: .infinity, maxHeight: .infinity)

}

}


This also crashes with the same error. Anyone else seeing this problem? It seems a well used construct that would be creating problems for others.

Replies

I was just about to post a very similar message since I am having the exact same issue. Note that it will even crash if there isn't a single @Published variable in the ObservableObject. I also added "final class" to the ObservableObject since they do that in the tutorials but that didn't help either. I'm hoping there is some workaround that someone has figured out.

In your code, there is no instanciation of the TestClass object so it's equal to nil and so the BAD_ACCESS error


Try

struct ContentView: View {
  @ObservedObject public var testObject = TestClass().   // Instanciation of the object
  var body: some View {
    Text(testObject.str).frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}



And if the object is instanciated elsewhere for example


import SwiftUI

public class TestClass: ObservableObject {
  @Published public var str: String = "Goodbye"
}

struct ContentView: View {
  @ObservedObject public var testObject: TestClass.   // instanciated elsewhere, here in the call of the view
  var body: some View {
    Text(testObject.str).frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

struct Test_Previews: PreviewProvider {
  static var previews: some View {
    ContentView(testObject: TestClass())    // Instanciation 
  }
}

I instantiate the object in the calling object (in this case AppDelegate.swift) and initialize it through the autogenerated init for ContentVIew. I did not include this code for brevity.


import Cocoa

import SwiftUI


@NSApplicationMain

class AppDelegate: NSObject, NSApplicationDelegate {

....

func applicationDidFinishLaunching(_ aNotification: Notification) {

...

window.contentView = NSHostingView(rootView: ContentView(testObject: TestClass()))


...

}

...

}

Oh ok it's a Mac App, I've never tried sorry.

mine is iOS, and instanciating in the SceneDelegate class, it works just fine


import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?
  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let windowScene = scene as? UIWindowScene {
      let window = UIWindow(windowScene: windowScene)
      window.rootViewController = UIHostingController(rootView: ContentView(testObject: TestClass())). // Instanciation
      self.window = window
      window.makeKeyAndVisible()
    }
  }

Perhaps I'll try a MacApp tomorrow and let you know, in France it's already the beginning of the night 😉

Hi,


We had an exchange yesteray about that ... it appears that using $testObject.str.wrappedValue does not work in your case.


Mine it was working because I pass my observable model object with environementObject, then in you case I succceeded to get the thing working with :


window.contentView = NSHostingView(rootView: ContentView().environmentObject(testObject))


and


struct ContentView: View {

@EnvironmentObject var obj: TestClass


var body: some View {

Text($obj.str.wrappedValue)

.frame(maxWidth: .infinity, maxHeight: .infinity)

}

}


Something is broken surely in SwiftUI and Combine for the time being... next beta we hope 🙂


Regards


Gerard

On another forum, I saw a comment that someone addressed this by making the class that conforms to ObservableObject a subclass of NSObject. I tried this change and it fixed the issue. I did not see anything in the documentation or the release notes indicating the class has to be a subclass of NSObject, but at least this apparently is a viable work around for now.


>>>>


import SwiftUI


public class TestClass: NSObject, ObservableObject {

@Published public var str: String = "Goodbye"

}


struct ContentView: View {

@ObservedObject public var testObject: TestClass

var body: some View {

Text(testObject.str)

.frame(maxWidth: .infinity, maxHeight: .infinity)

}

}

I have the same issue, your code is the same as mine and it just crashes.

I hope it will be fixed in next beta.

Is it fixed in Xcode 11 GM???

The above code (without NSObject) compiles and runs for me on Xode 11 GM and macos catalina beta 8.

Hey, I was able to get this working by importing Combine in the file that declared the public ObservableObject - no NSObject subclassing needed. Once I did this and added a public init... it worked! Give it a shot.

Just a note on subclassing NSObject, I'd avoid it, although my framework compiled fine with it, it failed to compile properly when I had another app pull in that framework.