iPad attempting to import Journaling Suggestions

I am using #canImport(JournalingSuggestions), but something is going wrong and my app is attempting to import the framework on iPad, and crashing on launch. How can I ensure that it's properly filtered out from everything except iPhone?

import SwiftUI
#if canImport(JournalingSuggestions)
import JournalingSuggestions
#endif

struct JournalingSuggestionsView: View {
    var body: some View {
        #if canImport(JournalingSuggestions)
            JournalingSuggestionsPicker {
                Text("Open Journaling Suggestions")
            } onCompletion: { suggestion in
                print(suggestion)
            }
        #else
            Text("Journaling suggestions not available on this platform.")
        #endif
    }
}

Error:

dyld[8689]: Library not loaded: /System/Library/Frameworks/JournalingSuggestions.framework/JournalingSuggestions
  Referenced from: <A656E6BC-4883-3245-BE71-3F84C2F41119> /private/var/containers/Bundle/Application/C6C11F57-AFAA-442A-B726-7AADDDB50D79/Catalog.app/Catalog
  Reason: tried: '/System/Library/Frameworks/JournalingSuggestions.framework/JournalingSuggestions' (no such file), '/private/preboot/Cryptexes/OS/System/Library/Frameworks/JournalingSuggestions.framework/JournalingSuggestions' (no such file), '/System/Library/Frameworks/JournalingSuggestions.framework/JournalingSuggestions' (no such file, not in dyld cache)

System info: Xcode 15.2 iPadOS 17.3.1

Answered by Vision Pro Engineer in 784514022

As an update to @eskimo 's response,

There's a few cases here:

  • Case #1: Building for the simulator.
  • Case #2: Building for a real device, but running on a device where the framework isn't present (eg: iPad, Mac)
  • Case #3: Building for an iOS version before iOS 17.2 where the framework isn't available

For case #1: use #if canImport(JournalingSuggestions) like this:

#if canImport(JournalingSuggestions)
    import JournalingSuggestions
#endif

Then, in your code where you use JournalingSuggestionsPicker, check if you can import it first. This way, if you're not building for a real device, the framework will not be imported.

For case #2: Since you're building for a real device, the framework can be imported. Since it's not an iPhone, your app will crash when run. Protect against this by first checking if you can import UIKit, then setting isJournalingSuggestionsAvailable to be true if you're on an iPhone. If you're on Mac, where UIKit can't be imported, isJournalingSuggestionsAvailable will be false anyways. For example:

#if canImport(UIKit)
import UIKit
let isJournalingSuggestionsAvailable = UIDevice.current.userInterfaceIdiom == .phone
#else
let isJournalingSuggestionsAvailable = false
#endif

In your code, where you use JournalingSuggestionsPicker, first check if you can import it with the info in case #1 above, then check if isJournalingSuggestionsAvailable is true.

For case #3: To handle the older iOS case, you need if #available(iOS 17.2, *)

Altogether, it looks like this in code:

#if canImport(JournalingSuggestions)
    if isJournalingSuggestionsAvailable {
        if #available(iOS 17.2, *) {
            JournalingSuggestionsPicker {
                Text("Choose a suggestion")
            } onCompletion: { suggestion in
                print("suggestion:", suggestion)
            }
        } else {
            Text("Requires iOS 17.2.")
        }
    } else {
        Text("Dynamically not available on this platform.")
    }
#else
    Text("Statically not available on this platform.")
#endif
}

Important - iPad weak linking

To ensure your app can run on iPad without crashing, you must weak link to the framework. The normal way to do this is via the Status column in the Link Binary With Libraries build phase. That doesn’t work here because the framework isn’t available on the iOS Simulator platform, so the simulator build fails, as @bryan1anderson pointed out. The workaround is to pass in -Xlinker -weak_framework -Xlinker JournalingSuggestions via the Other Linker Flags build setting.

Hi there! I'm still having the same issue. No matter which method I use, either the auto-linking, not the build setting trick. The problem I guess is that XCode will always look into it since we are conditional import the suggestion. The super weird part is that the import statement is active no matter if it's under #if canImport(JournalingSuggestions). In comparison, the code inside struct get disabled when I apply the #if. Any idea on what that happened? and is there a brutal way to just let me build without issues? Thanks.

iPad attempting to import Journaling Suggestions
 
 
Q