flutter
                                
                                 flutter copied to clipboard
                                
                                    flutter copied to clipboard
                            
                            
                            
                        iOS app crashing after integrating shared_preferences package in Flutter module
I'm working on an iOS app that uses Flutter as a module, and I recently added the shared_preferences: ^2.1.1 package to my Flutter module's pubspec.yaml file.
After running pod install --repo-update or pod install for the iOS native project, I noticed that a plugin called shared_preferences_foundation (version 0.0.1) was installed.
However, when I build the iOS app, it launches and then immediately crashes, showing me the errors in the screenshots below.
Expected results
The iOS should lunch and display a button to lunch the Flutter module.
Actual results
A black screen appears.
Code sample
ViewController.swift file where I lunch the Flutter module
import UIKit
import Flutter
class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(type: UIButton.ButtonType.custom)
        button.setTitle("Open Subz", for: UIControl.State.normal)
        button.frame = CGRect(x: 80.0, y: 210.0, width: 160.0, height: 40.0)
        button.center = self.view.center
        button.backgroundColor = UIColor.black
        self.view.addSubview(button)
        
        button.backgroundColor = UIColor.red
        button.addTarget(self, action: #selector(showFlutter), for: .touchUpInside)
        self.view.addSubview(button)
    }
    
    // When this function is called, CacheVC will be presented to the view
    @objc private func tapButton() {
        let vc = CacheVC()
        present(vc, animated: true)
    }
 
    // Defining Function To Show Flutter
    @objc func showFlutter() {
        let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
        let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
        flutterViewController.modalPresentationStyle = .fullScreen
        present(flutterViewController, animated: true, completion: nil)
        
        let hostIOSValue: String = "Congratulations"
        let hostIOSHeading: String = "Data Passed"
        let color: String = "green"
        
        // Channel for communicating with the Flutter Client
        let hostIOSChannel = FlutterMethodChannel(name: "app.factory/ios", binaryMessenger: flutterViewController.binaryMessenger)
        
        // Sending data from channel to Flutter Client
        let jsonObject: NSMutableDictionary = NSMutableDictionary()
        
        // Setting keys and values
        jsonObject.setValue(hostIOSValue, forKey: "heading")
        jsonObject.setValue(hostIOSHeading, forKey: "title")
        jsonObject.setValue(color, forKey: "color")
        
        var convertedString: String? = nil
        
        do {
            let data1 = try JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions.prettyPrinted)
            convertedString = String(data: data1, encoding: String.Encoding.utf8)
        } catch let myJSONError {
            print(myJSONError)
        }
        
        // This method is invoked on the UI thread.
        hostIOSChannel.invokeMethod("fromHostIOSToFlutterClient", arguments: convertedString)
    }
}
Screenshots
Logs
Xcode logs
objc[551]: Class PodsDummy_libwebp is implemented in both /private/var/containers/Bundle/Application/72D4D811-6F78-4EA8-B3C5-914BBC93C4DF/ios-native.app/Frameworks/libwebp.framework/libwebp (0x108078238) and /private/var/containers/Bundle/Application/72D4D811-6F78-4EA8-B3C5-914BBC93C4DF/ios-native.app/Frameworks/GiphyUISDK.framework/GiphyUISDK (0x1070a25d0). One of the two will be used. Which one is undefined.
2023-05-14 14:01:55.379365+0300 ios-native[551:12915] Warning: Unable to create restoration in progress marker file
2023-05-14 14:01:55.534639+0300 ios-native[551:12915] Metal API Validation Enabled
2023-05-14 14:01:55.708817+0300 ios-native[551:12915] GrMtlCommandBuffer: WARNING: Creating MTLCommandBuffer while in background.
2023-05-14 14:01:55.710231+0300 ios-native[551:12915] GrMtlCommandBuffer: WARNING: Creating MTLCommandBuffer while in background.
2023-05-14 14:01:55.764097+0300 ios-native[551:12915] <SKPaymentQueue: 0x2823e8590>: No observers found that respond to "paymentQueue:shouldAddStorePayment:forProduct:", will not check for purchase intents
2023-05-14 14:01:55.816235+0300 ios-native[551:13271] flutter: The Dart VM service is listening on http://127.0.0.1:49612/dsHbhucrhZ8=/
2023-05-14 14:01:55.867103+0300 ios-native[551:13245] 10.7.0 - [FirebaseMessaging][I-FCM001000] FIRMessaging Remote Notifications proxy enabled, will swizzle remote notification receiver handlers. If you'd prefer to manually integrate Firebase Messaging, add "FirebaseAppDelegateProxyEnabled" to your Info.plist, and set it to NO. Follow the instructions at:
https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in_firebase_messaging
to ensure proper integration.
2023-05-14 14:01:55.875097+0300 ios-native[551:13245] 10.7.0 - [FirebaseAnalytics][I-ACS023007] Analytics v.10.7.0 started
2023-05-14 14:01:55.875238+0300 ios-native[551:13245] 10.7.0 - [FirebaseAnalytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r)
(lldb) 
Flutter Doctor output
Doctor output
[!] Flutter (Channel stable, 3.7.12, on macOS 13.3.1 22E772610a darwin-arm64 (Rosetta), locale en-PS)
    • Flutter version 3.7.12 on channel stable at /Users/khader/fvm/versions/3.7.12
    ! Warning: `dart` on your path resolves to /usr/local/Cellar/dart/2.18.3/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/khader/fvm/versions/3.7.12. Consider adding /Users/khader/fvm/versions/3.7.12/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 4d9e56e694 (4 weeks ago), 2023-04-17 21:47:46 -0400
    • Engine revision 1a65d409c7
    • Dart version 2.19.6
    • DevTools version 2.20.1
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /Users/khader/Library/Android/sdk
    • Platform android-33, build-tools 33.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.12.1
[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
[✓] Android Studio (version 2021.3)
    • Android Studio at /Users/khader/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
[✓] VS Code (version 1.78.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.64.0
[✓] Connected device (3 available)
    • Khader Murtaja’s iPhone (mobile) • 00008110-001C38183609801E • ios            • iOS 16.4.1 20E252
    • macOS (desktop)                  • macos                     • darwin-arm64   • macOS 13.3.1 22E772610a darwin-arm64 (Rosetta)
    • Chrome (web)                     • chrome                    • web-javascript • Google Chrome 113.0.5672.92
[✓] HTTP Host Availability
    • All required HTTP hosts are available
! Doctor found issues in 1 category.
Please provide the code where you are calling the plugin registrant.
Please provide the code where you are calling the plugin registrant.
@stuartmorgan I just added it as a dependency within the pub spec.yaml file.
I'm referring to the call to [Generated plugin registrant register with registry]. That's not a plugin, it's native code that you are calling in the crashing stack; we need to see that code since it looks like you are calling it incorrectly.
@stuartmorgan, I'm using the AppDelegate.swift file, here ⬇️
AppDelegate.swift
import UIKit
import Flutter
import FlutterPluginRegistrant
import Firebase
import UserNotifications
import Shared
@main
class AppDelegate: FlutterAppDelegate, MessagingDelegate {
    
    // The FlutterEngine serves as a host to the Dart VM and the Flutter runtime
    lazy var flutterEngine = FlutterEngine(name: "Flutter Call")
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // Running Flutter Engine
        flutterEngine.run()
        
        FirebaseApp.configure()
        
        // [START set_messaging_delegate]
        Messaging.messaging().delegate = self
        // [END set_messaging_delegate]
        
        // Register for remote notifications. This shows a permission dialog on first run, to
        // show the dialog at a more appropriate time move this registration accordingly.
        // [START register_for_notifications]
        UNUserNotificationCenter.current().delegate = self
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in
            // NOTE: Add textfield to reply directly in notification popup
            let replyAction = UNTextInputNotificationAction(
                identifier: ReplyActionId,
                title: "Reply to the message",
                textInputButtonTitle: "Send",
                textInputPlaceholder: "Type reply here"
            )
            
            let pushNotificationButtons = UNNotificationCategory(
                identifier: MessageNotificationCategory,
                actions: [replyAction],
                intentIdentifiers: [],
                options: []
            )
            
            UNUserNotificationCenter.current().setNotificationCategories([pushNotificationButtons])
        }
        
        application.registerForRemoteNotifications()
        
        GeneratedPluginRegistrant.register(with: flutterEngine)
        GeneratedPluginRegistrant.register(with: self)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        messaging.token { token, _ in
            guard let token = token else {
                return
            }
        }
    }
    
    // MARK: UISceneSession Lifecycle
    
    override func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
    
    override func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
}
GeneratedPluginRegistrant.register(with: flutterEngine) GeneratedPluginRegistrant.register(with: self)
Calling GeneratedPluginRegistrant.register with a FlutterAppDelegate is only valid if your root view controller is a FlutterViewController. If it's not, then there's no way for the app delegate to locate the engine, and plugins will receive a nil registrant (and thus almost certainly crash).
If your intent is to have two different engines, one that you manage directly and one that's managed by a FlutterViewController, (which is the only reason I can think of to call this twice), you'll need to configure your application differently to allow calling with: self, or you'll need to replace self with an explicit reference to the other engine.
Closing as the issue here is with the add-to-app code, not Flutter.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.