Skip to content

Commit 6900327

Browse files
authored
Switch to approachable concurrency + default to main actor isolation (#2422)
* fix(concurrency): align main-actor isolation * fix(concurrency): apply main-actor default to UI packages * perf: offload stream decoding off main actor * fix(timeline): preserve remote timeline ids * Refactor stream event decoding logic Moved stream event decoding into a new StreamEventDecoder actor for sequential processing and improved error handling. Updated event emission methods to be public and streamlined error logging for decoding failures.
1 parent 64bc4e2 commit 6900327

30 files changed

Lines changed: 196 additions & 91 deletions

File tree

IceCubesApp.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,8 @@
728728
SUPPORTS_MACCATALYST = YES;
729729
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
730730
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
731+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
732+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
731733
SWIFT_EMIT_LOC_STRINGS = YES;
732734
SWIFT_VERSION = 6.0;
733735
TARGETED_DEVICE_FAMILY = "1,2,7";
@@ -764,6 +766,8 @@
764766
SUPPORTS_MACCATALYST = YES;
765767
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
766768
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
769+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
770+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
767771
SWIFT_EMIT_LOC_STRINGS = YES;
768772
SWIFT_VERSION = 6.0;
769773
TARGETED_DEVICE_FAMILY = "1,2,7";
@@ -801,6 +805,8 @@
801805
SKIP_INSTALL = YES;
802806
SUPPORTS_MACCATALYST = YES;
803807
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
808+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
809+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
804810
SWIFT_EMIT_LOC_STRINGS = YES;
805811
SWIFT_VERSION = 6.0;
806812
TARGETED_DEVICE_FAMILY = "1,2";
@@ -836,6 +842,8 @@
836842
SDKROOT = iphoneos;
837843
SKIP_INSTALL = YES;
838844
SUPPORTS_MACCATALYST = YES;
845+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
846+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
839847
SWIFT_EMIT_LOC_STRINGS = YES;
840848
SWIFT_VERSION = 6.0;
841849
TARGETED_DEVICE_FAMILY = "1,2";
@@ -871,6 +879,8 @@
871879
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
872880
SUPPORTS_MACCATALYST = YES;
873881
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
882+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
883+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
874884
SWIFT_EMIT_LOC_STRINGS = YES;
875885
SWIFT_VERSION = 6.0;
876886
TARGETED_DEVICE_FAMILY = "1,2";
@@ -905,6 +915,8 @@
905915
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
906916
SUPPORTS_MACCATALYST = YES;
907917
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
918+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
919+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
908920
SWIFT_EMIT_LOC_STRINGS = YES;
909921
SWIFT_VERSION = 6.0;
910922
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1092,6 +1104,8 @@
10921104
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
10931105
SUPPORTS_MACCATALYST = YES;
10941106
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1107+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
1108+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
10951109
SWIFT_EMIT_LOC_STRINGS = YES;
10961110
SWIFT_STRICT_CONCURRENCY = complete;
10971111
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
@@ -1161,6 +1175,8 @@
11611175
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
11621176
SUPPORTS_MACCATALYST = YES;
11631177
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1178+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
1179+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
11641180
SWIFT_EMIT_LOC_STRINGS = YES;
11651181
SWIFT_STRICT_CONCURRENCY = complete;
11661182
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
@@ -1208,6 +1224,8 @@
12081224
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
12091225
SUPPORTS_MACCATALYST = YES;
12101226
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1227+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
1228+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
12111229
SWIFT_EMIT_LOC_STRINGS = YES;
12121230
SWIFT_VERSION = 6.0;
12131231
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1243,6 +1261,8 @@
12431261
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
12441262
SUPPORTS_MACCATALYST = YES;
12451263
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1264+
SWIFT_APPROACHABLE_CONCURRENCY = YES;
1265+
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
12461266
SWIFT_EMIT_LOC_STRINGS = YES;
12471267
SWIFT_VERSION = 6.0;
12481268
TARGETED_DEVICE_FAMILY = "1,2";

IceCubesApp/App/Tabs/Settings/IconSelectorView.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,14 @@ struct IconSelectorView: View {
118118
LazyVGrid(columns: columns, spacing: 6) {
119119
ForEach(icons) { icon in
120120
Button {
121-
currentIcon = icon.appIconName
121+
let appIconName = icon.appIconName
122+
currentIcon = appIconName
122123
if icon.rawValue == Icon.primary.rawValue {
123124
UIApplication.shared.setAlternateIconName(nil)
124125
} else {
125-
UIApplication.shared.setAlternateIconName(icon.appIconName) { err in
126+
UIApplication.shared.setAlternateIconName(appIconName) { err in
126127
guard let err else { return }
127-
assertionFailure("\(err.localizedDescription) - Icon name: \(icon.appIconName)")
128+
assertionFailure("\(err.localizedDescription) - Icon name: \(appIconName)")
128129
}
129130
}
130131
} label: {

IceCubesApp/App/Tabs/Tabs.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ enum AppTab: Identifiable, Hashable, CaseIterable, Codable {
2222
case links
2323
case anyTimelineFilter(filter: TimelineFilter)
2424

25-
nonisolated var id: Int {
25+
var id: Int {
2626
return switch self {
2727
case .timeline: 0
2828
case .notifications: 1
@@ -47,7 +47,7 @@ enum AppTab: Identifiable, Hashable, CaseIterable, Codable {
4747
}
4848
}
4949

50-
nonisolated static var allCases: [AppTab] {
50+
static var allCases: [AppTab] {
5151
[.timeline,
5252
.notifications,
5353
.mentions,

IceCubesAppIntents/PostImageIntent.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ struct PostImageIntent: AppIntent {
2525
var altText: String?
2626

2727
func perform() async throws -> some IntentResult {
28-
AppIntentService.shared.handledIntent = .init(intent: self)
28+
await MainActor.run {
29+
AppIntentService.shared.handledIntent = .init(intent: self)
30+
}
2931
return .result()
3032
}
3133
}

IceCubesAppIntents/PostIntent.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ struct PostIntent: AppIntent {
1010
var content: String?
1111

1212
func perform() async throws -> some IntentResult {
13-
AppIntentService.shared.handledIntent = .init(intent: self)
13+
await MainActor.run {
14+
AppIntentService.shared.handledIntent = .init(intent: self)
15+
}
1416
return .result()
1517
}
1618
}

IceCubesAppIntents/TimelineFilterEntity.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import NetworkClient
77
import Timeline
88

99
public struct TimelineFilterEntity: Identifiable, AppEntity {
10-
public var id: String { timeline.id }
10+
public nonisolated var id: String { timeline.id }
1111

1212
public let timeline: TimelineFilter
1313

1414
public static let defaultQuery = DefaultTimelineEntityQuery()
1515

1616
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "TimelineFilter"
1717

18-
public var displayRepresentation: DisplayRepresentation {
18+
public nonisolated var displayRepresentation: DisplayRepresentation {
1919
DisplayRepresentation(title: "\(timeline.title)")
2020
}
2121
}

IceCubesNotifications/NotificationService.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import UserNotifications
1212
extension UNMutableNotificationContent: @unchecked @retroactive Sendable {}
1313

1414
class NotificationService: UNNotificationServiceExtension {
15-
override func didReceive(
15+
nonisolated override init() {
16+
super.init()
17+
}
18+
19+
nonisolated override func didReceive(
1620
_ request: UNNotificationRequest,
1721
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
1822
) {

IceCubesNotifications/NotificationServiceSupport.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import CryptoKit
22
import Foundation
33

44
extension NotificationService {
5-
static func decrypt(
5+
nonisolated static func decrypt(
66
payload: Data, salt: Data, auth: Data, privateKey: P256.KeyAgreement.PrivateKey,
77
publicKey: P256.KeyAgreement.PublicKey
88
) -> Data? {
@@ -49,7 +49,11 @@ extension NotificationService {
4949
return Data(unpadded)
5050
}
5151

52-
private static func info(type: String, clientPublicKey: Data, serverPublicKey: Data) -> Data {
52+
private nonisolated static func info(
53+
type: String,
54+
clientPublicKey: Data,
55+
serverPublicKey: Data
56+
) -> Data {
5357
var info = Data()
5458

5559
info.append("Content-Encoding: ".data(using: .utf8)!)

Packages/Account/Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ let package = Package(
3838
.product(name: "WrappingHStack", package: "WrappingHStack"),
3939
],
4040
swiftSettings: [
41-
.swiftLanguageMode(.v6)
41+
.swiftLanguageMode(.v6),
42+
.defaultIsolation(MainActor.self)
4243
]
4344
),
4445
.testTarget(

Packages/Account/Sources/Account/Detail/Tabs/Base/AccountTabProtocol.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import NetworkClient
44
import StatusKit
55
import SwiftUI
66

7+
@MainActor
78
public protocol AccountTabProtocol: Identifiable, Hashable {
89
associatedtype TabView: View
910

0 commit comments

Comments
 (0)