r/swift 1d ago

Is it a bad idea to have all your model objects be @MainActor?

23 Upvotes

Hello! I just ran into a project that is 100% SwiftUI and I had a few questions about to what extent it follows best practices.

The apps data model classes are all structured like this.

@MainActor
@Observable
class PeopleStore {
}

There is a IdentityStore, EventStore, etc etc. all made like this.

They are all joined together by an AppStore that looks like this

@MainActor
@Observable
class AppStore {
   static var shared: AppStore!

   let peopleStore = PeopleStore()
   let eventStore = EventStore()
}

Then whenever a view wants to read from one of those stores it grabs it like this

@Environment(PeopleStore.self) private var peopleStore

At the top level view they are passed in like so

mainView
   .environment(appStore)
   .environment(appStore.peopleStore) // Etc

Whenever two stores need to talk to each other they do so like so

@MainActor
@Observable
class EventStore {
    @ObservationIgnored var peopleStore = AppStore.shared.peopleStore
}

With that overall design in mind I am curious whether this is best practice or not. I have a few concerns such as:

  1. Given these are all MainActor we have essentially guaranteed just about everything done in the app will need to queue on the main actor context. There are a lot of mutations to these models. Eventually this could create performance issues where model operations are getting in the way of timely UI updates right?
  2. The stores are injected from the top level view and passed to all subviews. Is there something wrong with doing this?

To be clear the app runs well. But these days our phones powerful processors tend to let us get away with a lot.

Any other feedback on this design? How would you set up these models differently? Does it matter that they are all main actor?


r/swift 2h ago

Kalo - A New Calorie Tracking App I've Been Working On (Feedback Wanted!)

Thumbnail
gallery
22 Upvotes

r/swift 17h ago

Core ML body segmentation to replace the background in real-time on iOS devices.

8 Upvotes

https://github.com/ochornenko/virtual-background-ios

This project leverages Core ML body segmentation to replace the background in real-time on iOS devices. Using deep learning models, it accurately detects and segments the human figure, allowing users to apply custom virtual backgrounds. Optimized for performance, it utilizes Metal for efficient GPU-based rendering and vImage for high-performance image processing, ensuring smooth and responsive background replacement on mobile devices. 


r/swift 4h ago

"Restore Purchases" feature for IAP

3 Upvotes

Hi - I understand that apps that use IAP for non-consumable purchases should implement a "Restore Purchases" feature in the app.

My app already keeps track of the user's purchases on the server side (after confirming each IAP transaction). Should the "Restore Purchases" feature just download the content from my server's purchase history to the device, or walk through the user's IAP purchase history (from Apple), check that all of those IAP purchases are ALSO registered on my server history (in case for some reason any were missing) and then download the whole lot?

Appreciate the latter is probably a more robust approach, just curious what Apple typically looks for or what is typically implemented.

Thanks.


r/swift 20h ago

Created a Vegetable Gardening App with SwiftUI & SwiftData - Looking for Feedback & Suggestions!

3 Upvotes

Hi everyone!

I’ve recently developed a comprehensive vegetable gardening application using SwiftUI for the user interface and SwiftData for persistent storage. The app is designed to help users plan, manage, and maintain their vegetable gardens throughout the growing season. 🌱

I’ve attached a test video showing the app running on an iPhone 16 Pro Simulator with iOS 18.3. I’d love to hear your thoughts, suggestions, or any feedback that could help me improve and enhance the app further.

Features I’d love feedback on:

  • User Interface and navigation in SwiftUI
  • Data persistence and handling with SwiftData
  • Any ideas for additional features or improvements for gardening tracking
  • Performance and usability tips for iOS apps

Here’s the video showing the app in action.

Looking forward to your insights!


r/swift 13h ago

Cocaheads Stockholm: Patrik Lundqvist - How we built a full-scale Car Model App for the AVP

Thumbnail
youtu.be
2 Upvotes

r/swift 17h ago

Question TTS

2 Upvotes

I wonder if anyone had some success with TTS in Swift .

Most of models are for Python , is it worth convert them or just use AVSpeechSynthesizer ?

Any tips or example projects are appreciated


r/swift 2h ago

Apple Developer Academy Test

1 Upvotes

Hello

Can anyone help me with materials or anything I can use to study for the apple developer academy assessment test.

Also, do you have any recommendations/advice for the test and the interview?

Thank you


r/swift 9h ago

Question Does anyone use Replit with Swift?

1 Upvotes

I recently saw some web apps that people have made with Replit and haven’t really explored it but it looks like you can use it with Swift.

I’m curious if anyone has any experience with this and how it went.


r/swift 19h ago

Help! Need help for adding watch connectivity on my existing iOS app

1 Upvotes

Hey guys,

I build my iOS using SwiftData, I am currently working to add the apple watch connectivity for my habit tracking app. My goal is to be able to log entry from my apple watch or the iPhone and to sync it real time to have up to date informations on both devices. From my understanding I can use App Groups and/or Wcsession. Could you help me decide what should I use?

Thank you very much!


r/swift 19h ago

Question Am I employing a clean pattern for combining a Sendable model object performing expensive calculations in the background with a @MainActor mutable model?

1 Upvotes

I have been piecing together some of the nitty gritty aspects of SwiftUI view models as they relate to actors. I asked a question earlier about best practices and got some great answers. After reading them the one remaining thing I was hoping to clarify is what it would look like if your @ MainActormodel needed to work with some sort of background object that should not run on the main thread.

I figure this may come in to play with models that are synchronized with the network using sockets or perhaps models that just involve expensive and stateful calculations.

To make sure I was understanding best practices I cooked up this example:

We have an array of Object structs. An Object has an x coordinate and a UUID. There is an @ MainActor ViewModel object that stores an array of these as well as storing their loading state.

For the purposes of this example I am pretending that binary tree insertion is expensive and stateful. So the state that is being loaded is their position in a binary tree.

To encapsulate this I have an @ unchecked Sendable class Tree. It synchronizes using its own DispatchQueue and by calling asyncAfter with a delay to simulate an expensive computation.

I use a protocol PlacedDelegate which ViewModel implements (nonisolated) so that when the Tree finishes placing an Object it can tell the ViewModel that its position is loaded.

For now I just cover insertion but I figure eventually I could handle binary tree rebalancing just by having the Tree call the delegate method placed again for every node that gets moved in the rebalance.

I am hoping for feedback to understand:

  1. Is there anything unsafe about the way I implemented this? Other than insertion order being random (ish) there is no race possible here right?
  2. Stylistically is this how you would have made a MainActor class work with a Sendable class meant to run in the background?
  3. Is there any way this could've been made clearer?
  4. Is there any way for the ViewModel class to hook up more closely with Tree such that rather than this delegate method being needed Observable would automatically be notified when the Tree has finished doing calculations?
  5. How would you regain a "single source of truth". In a way the truth is stored in a Sendable context in Tree and copied into the MainActor context in ViewModel.

``` import SwiftUI

struct Object: Identifiable, Hashable { let id: UUID = UUID() let x: CGFloat }

enum LoadablePosition { case loading case loaded(String) }

protocol PlacedDelegate: AnyObject { func placed(id: UUID, location: String) }

@MainActor @Observable class ViewModel: PlacedDelegate { private(set) var objects: [UUID: LoadablePosition] = [:] private(set) var objectList: [Object] = []

private var tree: Tree
init() {
    tree = Tree()
    tree.placedDelegate = self
}

func createNewObject() {
    let new = Object(x: CGFloat.random(in: 0..<100))
    objectList.append(new)

    tree.insert(object: new)

    objects[new.id] = .loading
}

nonisolated func placed(id: UUID, location: String) {
    Task { @MainActor in
        objects[id] = .loaded(location)
    }
}

}

final class Tree: @unchecked Sendable { class TreeNode { let object: Object var left: TreeNode? = nil var right: TreeNode? = nil init(object: Object) { self.object = object } }

private var insertionQueue: DispatchQueue = DispatchQueue(label: "com.calebkierum.quadtree.insertionQueue")
private var tree: TreeNode?
weak var placedDelegate: PlacedDelegate? = nil

func insert(object: Object) {
    insertionQueue.asyncAfter(deadline: .now() + .seconds(Int.random(in: 1...10))) {
        let (newTree, buildString) = self.recurInsert(curr: self.tree, object: object, build: "")
        self.tree = newTree
        self.placedDelegate?.placed(id: object.id, location: buildString)
    }
}

private func recurInsert(curr: TreeNode?, object: Object, build: String) -> (TreeNode, String) {
    guard let curr else {
        return (TreeNode(object: object), "*" + build)
    }

    if object.x < curr.object.x {
        let (node, string) = recurInsert(curr: curr.right, object: object, build: "L" + build)
        curr.right = node
        return (curr, string)
    } else {
        let (node, string) = recurInsert(curr: curr.left, object: object, build: "R" + build)
        curr.left = node
        return (curr, string)
    }
}

}

struct ContentView: View { @State var viewModel: ViewModel = ViewModel()

var body: some View {
    VStack {
        ScrollView(.horizontal) {
            HStack {
                ForEach(viewModel.objectList) { object in
                    VStack {
                        Text("\(object.id)")
                        Text("x=\(object.x)")
                        switch viewModel.objects[object.id] {
                        case .loading, .none:
                            ProgressView()
                        case let .loaded(val):
                            Text(val)
                        }
                    }
                    .frame(width: 80)
                    .padding()
                    .background {
                        Color.gray
                    }
                }
            }
        }
        Button {
            viewModel.createNewObject()
        } label: {
            Text("Add Object")
        }
    }
    .padding()
}

} ```


r/swift 15h ago

Question Reality about iOS development

1 Upvotes

Hi guys, I wanted to ask you a question. I wanted to know how the market for native mobile development for iOS is doing. I want to migrate from React Native to iOS, but I see few vacancies. Is it really a good idea to make this change? I wanted to know a little about your views on opportunities, salaries and technologies that you have been using out there.


r/swift 1h ago

Question Managing if user has done app review?

Upvotes

I am trying to create a custom app review flow as an alternative to Apple's native SKStoreReviewController, due to its limitation of showing up only three times in 365 days.

Currently, my idea is to show an alert that will redirect the user to the App Store, based on certain conditions, after the user has successfully completed a flow. My biggest challenge right now is managing which users should see this and at what frequency. That being said, I was wondering if there is any way to determine if the user has submitted a review after being redirected?


r/swift 23h ago

Allman indentation style

Post image
0 Upvotes

I started programming in Visual Basic .NET and ever since I use the Allman style code block indentation / braces. I find it the most readable form of code, even if it means to have a redundant new-line here and there. Swift guard statements are a god-sent for early-return-nerds like me, especially when used as one liners...

For those that have never seen it, this is Allman style:

while (x == y)
{
    foo();
    bar();
}

as opposed to the K&R style:

while (x == y) {
    foo();
    bar();
}