realm / realm/SwiftLint

`@ObservedObject` shound't be initialized inside the `SwiftUI.View`

Open
#6,829 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
19.7k
Forks
2.3k
Avg merge
1d 1h
Merged PRs (30d)
11

Description

New Issue Checklist
New Rule Request

Please describe the rule idea, format this issue's title as Rule Request: [Rule Name] and describe:

New Rule Request:

  1. Why should this rule be added?
    Apple's documentation is explicit that a view must not create an @ObservedObject@ObservedObject doesn't own the object's lifetime, so initializing one inside a View is unsafe: SwiftUI can recreate the view at any time, which re-instantiates the object (silently resetting its state) and, during teardown/animation, can leave SwiftUI's internal box referencing a deallocated object → EXC_BAD_ACCESS use-after-free crashes (ObservedObjectPropertyBox.updateobjc_msgSend). The correct wrappers are @StateObject (view owns it) or @Observable (Observation). This rule flags objects created inside an @ObservedObject.
  • Apple: @ObserverdObject / @ObservedObject ("use @StateObject … to ensure consistent results" / don't create observed objects in a view) - "Don’t specify a default or initial value for the observed object. Use the attribute only for a property that acts as an input for a view, as in the above example."
  • Hacking with Swift - "Tip: It is really important that you use @ObservedObject only with views that were passed in from elsewhere. You should not use this property wrapper to create the initial instance of an observable object – that’s what @StateObject is for.
  • SwiftLee — @StateObject vs @ObservedObject
  1. Examples
    Triggers a violation (object created in the view):
@ObservedObject var viewModel = ViewModel()
@ObservedObject private var loader = Loader(url: url)
init() { self._state = ObservedObject(wrappedValue: LoadState()) }

Does not trigger (injected, not created):

@ObservedObject var viewModel: ViewModel           // set from init parameter
init(viewModel: ViewModel) { self.viewModel = viewModel }
@StateObject var viewModel = ViewModel()           // owned via @StateObject
@State var model = Model()                          // @Observable model
  1. Configurable?
    Not.

  2. Opt-in or default?
    Opt-in.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing existing SwiftUI-specific rule implementations and their rule tests, then use the provided violating and non-violating examples as fixtures. Add an opt-in rule that distinguishes objects initialized under @ObservedObject from injected properties, and verify that the examples produce the expected violations.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
tooling
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.