Revealed on: June 27, 2025
Up to date on: July 7, 2025
Swift 6.2 comes with a number of high quality of life enhancements for concurrency. One in every of these options is the flexibility to have actor-isolated conformances to protocols. One other characteristic is that your code will now run on the primary actor by default.
This does imply that typically, you’ll run into compiler errors. On this weblog submit, I’ll discover these errors, and how one can repair them while you do.
Earlier than we do, let’s briefly speak about actor-isolated protocol conformance to grasp what this characteristic is about.
Understanding actor-isolated protocol conformance
Protocols in Swift can require sure features or properties to be nonisolated. For instance, we are able to outline a protocol that requires a nonisolated var title like this:
protocol MyProtocol {
nonisolated var title: String { get }
}
class MyModelType: MyProtocol {
var title: String
init(title: String) {
self.title = title
}
}Our code is not going to compile in the meanwhile with the next error:
Conformance of 'MyModelType' to protocol 'MyProtocol' crosses into predominant actor-isolated code and might trigger information racesIn different phrases, our MyModelType is remoted to the primary actor and our title protocol conformance isn’t. Because of this utilizing MyProtocol and its title in a nonisolated means, can result in information races as a result of title isn’t truly nonisolated.
If you encounter an error like this you’ve got two choices:
- Embrace the
nonisolatednature oftitle - Isolate your conformance to the primary actor
The primary resolution normally signifies that you don’t simply make your property nonisolated, however you apply this to your total sort:
nonisolated class MyModelType: MyProtocol {
// ...
}This would possibly work however you’re now breaking out of predominant actor isolation and doubtlessly opening your self as much as new information races and compiler errors.
When your code runs on the primary actor by default, going nonisolated is usually not what you need; all the pieces else remains to be on predominant so it is smart for MyModelType to remain there too.
On this case, we are able to mark our MyProtocol conformance as @MainActor:
class MyModelType: @MainActor MyProtocol {
// ...
}By doing this, MyModelType conforms to my protocol however solely after we’re on the primary actor. This mechanically makes the nonisolated requirement for title pointless as a result of we’re at all times going to be on the primary actor after we’re utilizing MyModelType as a MyProtocol.
That is extremely helpful in apps which are predominant actor by default since you don’t need your predominant actor sorts to have nonisolated properties or features (normally). So conforming to protocols on the primary actor makes a whole lot of sense on this case.
Now let’s take a look at some errors associated to this characteristic, lets? I initially encountered an error round my SwiftData code, so let’s begin there.
Fixing Foremost actor-isolated conformance to ‘PersistentModel’ can’t be utilized in actor-isolated context
Let’s dig proper into an instance of what can occur while you’re utilizing SwiftData and a customized mannequin actor. The next mannequin and mannequin actor produce a compiler error that reads “Foremost actor-isolated conformance of ‘Train’ to ‘PersistentModel’ can’t be utilized in actor-isolated context”:
@Mannequin
class Train {
var title: String
var date: Date
init(title: String, date: Date) {
self.title = title
self.date = date
}
}
@ModelActor
actor BackgroundActor {
func instance() {
// Name to predominant actor-isolated initializer 'init(title:date:)' in a synchronous actor-isolated context
let train = Train(title: "Working", date: Date())
// Foremost actor-isolated conformance of 'Train' to 'PersistentModel' can't be utilized in actor-isolated context
modelContext.insert(train)
}
}There’s truly a second error right here too as a result of we’re calling the initializer for train from our BackgroundActor and the init for our Train is remoted to the primary actor by default.
Fixing our downside on this case signifies that we have to enable Train to be created and used from non-main actor contexts. To do that, we are able to mark the SwiftData mannequin as nonisolated:
@Mannequin
nonisolated class Train {
var title: String
var date: Date
init(title: String, date: Date) {
self.title = title
self.date = date
}
}Doing this can make each the init and our conformance to PersistentModel nonisolated which suggests we’re free to make use of Train from non-main actor contexts.
Observe that this does not imply that Train can safely be handed from one actor or isolation context to the opposite. It simply signifies that we’re free to create and use Train cases away from the primary actor.
Not each app will want this or encounter this, particularly while you’re operating code on the primary actor by default. In case you do encounter this downside for SwiftData fashions, it’s best to most likely isolate the problematic are to the primary actor until you particularly created a mannequin actor within the background.
Let’s check out a second error that, so far as I’ve seen is fairly frequent proper now within the Xcode 26 beta; utilizing Codable objects with default actor isolation.
Fixing Conformance of protocol ‘Encodable’ crosses into predominant actor-isolated code and might trigger information races
This error is sort of attention-grabbing and I ponder whether it’s one thing Apple can and may repair in the course of the beta cycle. That mentioned, as of Beta 2 you would possibly run into this error for fashions that conform to Codable. Let’s take a look at a easy mannequin:
struct Pattern: Codable {
var title: String
}This mannequin has two compiler errors:
- Round reference
- Conformance of ‘Pattern’ to protocol ‘Encodable’ crosses into predominant actor-isolated code and might trigger information races
I’m not precisely certain why we’re seeing the primary error. I believe it is a bug as a result of it is unnecessary to me in the meanwhile.
The second error says that our Encodable conformance “crossed into predominant actor-isolated code”. In case you dig a bit deeper, you’ll see the next error as an evidence for this: “Foremost actor-isolated occasion technique ‘encode(to:)’ can’t fulfill nonisolated requirement”.
In different phrases, our protocol conformance provides a predominant actor remoted implementation of encode(to:) whereas the protocol requires this technique to be non-isolated.
The rationale we’re seeing this error just isn’t totally clear to me however there appears to be a mismatch between our protocol conformance’s isolation and our Pattern sort.
We will do certainly one of two issues right here; we are able to both make our mannequin nonisolated or constrain our Codable conformance to the primary actor.
nonisolated struct Pattern: Codable {
var title: String
}
// or
struct Pattern: @MainActor Codable {
var title: String
}The previous will make it in order that all the pieces on our Pattern is nonisolated and can be utilized from any isolation context. The second possibility makes it in order that our Pattern conforms to Codable however solely on the primary actor:
func createSampleOnMain() {
// that is tremendous
let pattern = Pattern(title: "Pattern Occasion")
let information = attempt? JSONEncoder().encode(pattern)
let decoded = attempt? JSONDecoder().decode(Pattern.self, from: information ?? Knowledge())
print(decoded)
}
nonisolated func createSampleFromNonIsolated() {
// this isn't tremendous
let pattern = Pattern(title: "Pattern Occasion")
// Foremost actor-isolated conformance of 'Pattern' to 'Encodable' can't be utilized in nonisolated context
let information = attempt? JSONEncoder().encode(pattern)
// Foremost actor-isolated conformance of 'Pattern' to 'Decodable' can't be utilized in nonisolated context
let decoded = attempt? JSONDecoder().decode(Pattern.self, from: information ?? Knowledge())
print(decoded)
}So usually talking, you don’t need your protocol conformance to be remoted to the primary actor in your Codable fashions in case you’re decoding them on a background thread. In case your fashions are comparatively small, it’s possible completely acceptable so that you can be decoding and encoding on the primary actor. These operations ought to be quick sufficient usually, and sticking with predominant actor code makes your program simpler to motive about.
One of the best resolution will rely in your app, your constraints, and your necessities. At all times measure your assumptions when potential and follow options that be just right for you; don’t introduce concurrency “simply to make sure”. In case you discover that your app advantages from decoding information on a background thread, the answer for you is to mark your sort as nonisolated; in case you discover no direct advantages from background decoding and encoding in your app it’s best to constrain your conformance to @MainActor.
In case you’ve carried out a customized encoding or decoding technique, you could be operating into a special error…
Conformance of ‘CodingKeys’ to protocol ‘CodingKey’ crosses into predominant actor-isolated code and might trigger information races
Now, this one is slightly trickier. When we have now a customized encoder or decoder, we’d additionally need to present a CodingKeys enum:
struct Pattern: @MainActor Decodable {
var title: String
// Conformance of 'Pattern.CodingKeys' to protocol 'CodingKey' crosses into predominant actor-isolated code and might trigger information races
enum CodingKeys: CodingKey {
case title
}
init(from decoder: any Decoder) throws {
let container = attempt decoder.container(keyedBy: CodingKeys.self)
self.title = attempt container.decode(String.self, forKey: .title)
}
}Sadly, this code produces an error. Our conformance to CodingKey crosses into predominant actor remoted code and which may trigger information races. Often this could imply that we are able to constraint our conformance to the primary actor and this could clear up our problem:
// Foremost actor-isolated conformance of 'Pattern.CodingKeys' to 'CustomDebugStringConvertible' can't fulfill conformance requirement for a 'Sendable' sort parameter 'Self'
enum CodingKeys: @MainActor CodingKey {
case title
}This sadly doesn’t work as a result of CodingKeys requires us to be CustomDebugStringConvertable which requires a Sendable Self.
Marking our conformance to predominant actor ought to imply that each CodingKeys and CodingKey are Sendable however as a result of the CustomDebugStringConvertible is outlined on CodingKey I believe our @MainActor isolation doesn’t carry over.
This may also be a tough edge or bug within the beta; I’m undecided.
That mentioned, we are able to repair this error by making our CodingKeys nonisolated:
struct Pattern: @MainActor Decodable {
var title: String
nonisolated enum CodingKeys: CodingKey {
case title
}
init(from decoder: any Decoder) throws {
let container = attempt decoder.container(keyedBy: CodingKeys.self)
self.title = attempt container.decode(String.self, forKey: .title)
}
}This code works completely tremendous each when Pattern is nonisolated and when Decodable is remoted to the primary actor.
Each this problem and the earlier one really feel like compiler errors, so if these get resolved throughout Xcode 26’s beta cycle I’ll ensure to come back again and replace this text.
In case you’ve encountered errors associated to actor-isolated protocol conformance your self, I’d love to listen to about them. It’s an attention-grabbing characteristic and I’m making an attempt to determine how precisely it suits into the way in which I write code.

