Main actor-isolated property can not be referenced

Hello

I'm getting this error in my code and I don't know why. Can somebody explain this or point me at a help article.

import UIKit

var greeting = "Hello, playground"

let imageView = UIImageView()
imageView.image = UIImage(named: "image")
Utils.getImageSize(view: imageView)

class Utils {
    static func getImageSize(view imageView: UIImageView) {
        let image = imageView.image
        print("Image size = \(image?.size ?? CGSize.zero)")
    }
}

The error is as follows:

Cheers Murray

Answered by DTS Engineer in 850076022

It’s hard to say for sure what’s going on without seeing the full playground. I suspect you have a class like this:

class MyImageView: UIView {
    var image: UIImage? = nil
    func getImage() -> UIImage {
        fatalError()
    }
}

If so, I can explain this:

I don't understand why it needs to run on the main thread?

MyImageView is a subclass of UIView and UIView is main actor isolated. Thus the getImage() method is also isolated to the main actor. In your original implementation, Utils.getImageSize(…) wasn’t isolated to the main actor, and thus could be running on any thread. Thus you have non-isolated code calling isolated code, and the compiler complains.

Isolating Utils to the main actor resolves this problem.

In the long term I expect that UIView playgrounds will use approachable concurrency to default everything to the main actor, and this sort of code will just work out the box.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Is this in the Swift Playgrounds app? Or in an Xcode playground? And if it’s Xcode, what version of Xcode?

This matters because Swift is currently rolling a technology known as approachable concurrency, and it’s likely that you’ll want to use this for simple UI-focused programs like the one you posted. So, the best path forward here depends on whether you can use approachable concurrency or not.

For more on this rollout, watch:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer Hi Quinn

Just to be super clear:

As I woke up this morning I was thinking about the basics of what I was trying to do in this test. It did occur to me that perhaps the ".image" variable is private, so I made some changes to the test. As you can see, even with the public function the same error message appears.

So I watched the video "What's new in Swift" and they mentioned @MainActor and this triggered my memory. So I added this before the class and voila the error went away.

I'm just so confused though. "Utils" and "getImageSize" is a static function - even if called on another thread it is only operating on the object instance being passed in. I don't understand why it needs to run on the main thread??? Can you explain this please?

It’s hard to say for sure what’s going on without seeing the full playground. I suspect you have a class like this:

class MyImageView: UIView {
    var image: UIImage? = nil
    func getImage() -> UIImage {
        fatalError()
    }
}

If so, I can explain this:

I don't understand why it needs to run on the main thread?

MyImageView is a subclass of UIView and UIView is main actor isolated. Thus the getImage() method is also isolated to the main actor. In your original implementation, Utils.getImageSize(…) wasn’t isolated to the main actor, and thus could be running on any thread. Thus you have non-isolated code calling isolated code, and the compiler complains.

Isolating Utils to the main actor resolves this problem.

In the long term I expect that UIView playgrounds will use approachable concurrency to default everything to the main actor, and this sort of code will just work out the box.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I watched the second video "Embracing Swift Concurrency". I'm not really embracing it yet, and the concept of Isolation is quite foreign. However, the video did make some sense. All of the UI stuff needs to use @MainActor. Swift 6.2 will make this easier as it will be a default mode.
Thanks for your help Quinn.
PS More questions coming...

Main actor-isolated property can not be referenced
 
 
Q