How does Swift's "silent" import work?

Just for some context:
People sometimes say "A file containing a ViewModel should never import UIKit".
As if not importing UIKit in a file would be a guarantee that the file doesn't depend on UIKit, which you can verify is not the case by doing the following.

  1. In eg SceneDelegate.swift, define a global constant of some UIKit type:

    let someUIColor = UIColor.systemPink
  2. In some other file, that does not import UIKit, use that global and note that it compiles anyway:

    struct MyViewModel {
      let color = someUIColor

    So not importing UIKit didn't stop my view model from depending on UIKit ...
    Writing out the type explicitly will result in an error though:

    struct MyViewModel {
      let color: UIColor = someUIColor // ERROR: Cannot find type 'UIColor' in scope

What's behind this seemingly erratic behavior, ie why does it compile or not depending on whether the type is inferred or explicit?

You can use names from:

  • The file you're in, unless they're private to a type you're not in
  • The module you're in, if those names are internal, public or open;
  • The modules you import.

someUIColor is a name in your module. UIColor is not, and files that use it need to import UIKit before mentioning it.

Terms of Service

Privacy Policy

Cookie Policy