将数据从Flutter传递到SwiftUI主屏幕WidgetExtension?访问SQLite数据库本身还是使用met



我有一个flutter应用程序,它使用SQFLite来持久化数据。我有兴趣尝试做一个iOS主屏幕小部件,根据我所能收集到的信息,它必须在swiftui中构建。我想知道是否可以从Swiftui中的本地小部件访问我的flutter sqlite数据库?

更新:正在尝试使用以下建议,但遇到问题。由于如果我添加appdelegate模块作为共享目标,小部件扩展似乎会导致xcode构建失败。。。。我正试图把它跳转到一个快速文件调用,然后分享它。但我遇到了错误。

我的Flutter助手(它目前只是试图或多或少地从列表计数中发送一个整数作为概念证明(

import 'package:flutter/services.dart';
import 'dart:async';
import 'db.dart';

final channelName = 'widgetDataCheckItOff';
Future<void> _handleMethod(MethodCall call) async {
final String utterance = call.arguments;
switch(call.method) {
case "getDataFromFlutter":
var db = new DB();
dynamic result = await db.widgetQuery();
return result;
}
final methodChannel = MethodChannel(channelName);
methodChannel.setMethodCallHandler(_handleMethod);
}

AppDelegate

import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var controller : FlutterViewController!;
var widgetDataCheckItOff : FlutterMethodChannel!;
class func shared() -> AppDelegate
{
return UIApplication.shared.delegate as! AppDelegate
}

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
controller = window?.rootViewController as? FlutterViewController;
widgetDataCheckItOff = FlutterMethodChannel (
name : "widgetDataCheckItOff",
binaryMessenger : controller as! FlutterBinaryMessenger
)

GeneratedPluginRegistrant.register(with: self)
if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
@available(iOS 9.0, *)
override func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
let controller = window.rootViewController as? FlutterViewController

let channel = FlutterMethodChannel(name: "plugins.flutter.io/quick_actions", binaryMessenger: controller! as! FlutterBinaryMessenger)
channel.invokeMethod("launch", arguments: shortcutItem.type)
}
public func getTasks ( args: String, completion:@escaping (Int) -> Int) {
var x = -1
widgetDataCheckItOff.setMethodCallHandler { (call : FlutterMethodCall, result: @escaping FlutterResult) in
//        print("set method call handler")
if(call.method == "getDataFromFlutter") {
self.widgetDataCheckItOff.invokeMethod ("getDataFromFlutter", arguments: args, result: {(r:Any?) -> () in
x=r as! Int
});
}
else{
result(FlutterMethodNotImplemented)
x = -1// to handle undeclared methods
}
let result = x
completion(result)
}
}

}

跳跃文件我称小工具Swift

import Foundation
@objc class WidgetData: NSObject{
public func getWidgetData(result: Int)-> Int {
var x = -1
let a = UIApplication.shared.delegate as! AppDelegate
a.getTasks(args: "getDataFromFlutter",  completion: {(result) -> Int in
x = result
})
return x
//        let x = AppDelegate.getTasks(<#T##self: AppDelegate##AppDelegate#>);

}
}

我的小部件扩展部分称之为

struct widget_extension_widgetEntryView : View {
var entry: Provider.Entry
var body: some View {
let w = WidgetData()
let x: Int =         w.getWidgetData(result: <#Int#>)

let str = "Today's Tasks:  (x)"
Text("", tableName: str)
}
}

扩展名在函数调用中给了我错误:源文件中的Editor占位符。

小部件Swift在getTasks调用中给了我错误:在作用域中找不到"AppDelegate"声明的闭包结果"(("与上下文类型"Int"不兼容

Flutter提供了一种使用MethodChannel与本机平台代码进行通信的方法。

来自颤振MethodChannel文件(此处(:

Flutter使用一个灵活的系统,允许您调用特定于平台的API,无论是在Android上的Kotlin或Java代码中,还是在iOS上的Swift或Objective-C代码中。

注意:如果需要,方法调用也可以反向发送,平台充当Dart中实现的方法的客户端。一个具体的例子是quick_actions插件。

MethodChannel用于从flutter调用本机平台代码上的函数:

我们在Flutter、iOS和Android中创建了一个同名的方法通道对象。Android和iOS对象将设置一个方法调用处理程序来接收来自Flutter的调用。Flutter代码可以调用invokeMethod来调用本地对象上的处理程序

颤振:

static final channelName = 'com.example.widget/database';
final methodChannel = MethodChannel(channelName);
await this.methodChannel.invokeMethod("getDataFromDatabase");

安卓系统:

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.widget/database";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("getDataFromDatabase")) {
//TODO: Perform method to query database here
String data;
if (data != null) {
result.success(data);
} else {
result.error("UNAVAILABLE", "Data not available", null);
}
} else {
result.notImplemented();
}
}
);
}
}

iOS:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example.widget/database",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getDataFromDatabase" else {
result(FlutterMethodNotImplemented)
return
}
//TODO: Perform method to query database here
let data;
if data == nil {
result(FlutterError(code: "UNAVAILABLE",
message: "Data not available",
details: nil))
} else {
result(data)
}     
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

反向示例-从本机调用Flutter如果您需要从本机代码调用Flutter中定义的方法,那么您可以调用以前的相同方法,但这次您在Flutter端调用setMethodCallHandler,在本机端调用invokeMethod

颤振:

final channelName = 'dataFromFlutterChannel';
final methodChannel = MethodChannel(channelName);
methodChannel.setMethodCallHandler(this._handleMethod);
Future<void> _handleMethod(MethodCall call) async {
final String utterance = call.arguments; 
switch(call.method) {
case "getDataFromFlutter":
//TODO: Query database here and return the data to native side
}
}

安卓:

val channelName = 'dataFromFlutterChannel'
val methodChannel = MethodChannel(flutterView, channelName)

methodChannel.invokeMethod("getDataFromFlutter", utterance)

iOS:

let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
let channelName = "dataFromFlutterChannel"
let methodChannel = FlutterEventChannel(name: channelName, binaryMessenger: rootViewController)

methodChannel.invokeMethod("getDataFromFlutter", utterance)

这篇文章可以帮助你进行更详细的解释。

最新更新