0

I'm trying to archive my App so I can publish it but the archive fails with this error:

'guard' body must not fall through, consider using a 'return' or 'throw' to exit the scope

I've changed my code from this:

guard
      let nibObjects = Bundle.main.loadNibNamed("NativeAdView", owner: nil, options: nil),
      let adView = nibObjects.first as? GADNativeAdView
    else {
      assert(false, "Could not load nib file for adView")
    }
    setAdView(adView)
    refreshAd()

To this:

 guard false else {
          guard
            let nibObjects = Bundle.main.loadNibNamed("NativeAdView", owner: nil, options: nil),
            let adView = nibObjects.first as? GADNativeAdView
          else {
            assert(false, "Could not load nib file for adView")
          }
          setAdView(adView)
          refreshAd()
          return
      }

but I still get the same error!

The strange thing is that when I test my App on my device or simulator, I don't get any errors at all!

This error only happens during the archive.

Asperi
  • 228,894
  • 20
  • 464
  • 690
drago
  • 1,148
  • 2
  • 16
  • 35

3 Answers3

2

If you believe the path of execution should never pass through this point, the way to express this is to change

assert(false, "Could not load nib file for adView")

To

fatalError("Could not load nib file for adView")

Or simply return if you want to behave normally and safely.

Saying assert(false) was always the wrong way to go about this; there is never a reason to assert false, as it can never be true. Assertions are for verifying that what you believe true is true, not for playing mind games with the compiler. When programming, say the thing you mean, and not some tricky other thing.

matt
  • 515,959
  • 87
  • 875
  • 1,141
2

During the archive process the configuration is no more debug, that means all asserts are omitted and you have no exit command in the else case. Use return beside the assert:

guard condition else { assertionFailure(); return }

or (not recommended)

guard condition else { fatalError() }
Vadim Zhuk
  • 334
  • 2
  • 10
  • 1
    Actually, I think `fatalError()` is appropriate in this case. That code path is only executed if the app doesn't contain the nib. That would mean it hasn't been built properly and so, probably the only thing to do is fail hard and fast. – JeremyP Feb 02 '22 at 12:53
  • It will fail on user's side, what I believe is really unwanted, but assert is enough to crash in debug. – Vadim Zhuk Feb 04 '22 at 08:07
  • It's a programming error. It's similar to indexing off the end of an array or force unwrapping `nil`. It should abort (and ideally send a crash report to the developer). The app bundle is compromised so you can't safely carry on, especially as this is a nib and the UI is likely to be non functional. – JeremyP Feb 09 '22 at 10:52
  • Yes, right, but I prefer logging and non fatal reports, avoid any possible crashes in prod – Vadim Zhuk Feb 10 '22 at 12:31
  • Yes, but, in the specific instance where there are resources missing from an app bundle, it's almost certainly impossible to carry on because the UI is broken. There's no general rule, but in this case, the app bundle is corrupted. – JeremyP Mar 14 '22 at 08:59
0

assert is not run in production builds or doesn't have to fail, so you still need

assert(false)
return

in the body of else

PS. For always failing asserts use assertionFailure and if this is supposed to also fail on production, use preconditionFailure

Alistra
  • 5,177
  • 2
  • 30
  • 42