首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Pigeon包从Flutter调用原生iOS函数?

如何使用Pigeon包从Flutter调用原生iOS函数?
EN

Stack Overflow用户
提问于 2021-07-04 23:19:03
回答 1查看 323关注 0票数 1

我正在尝试将一些本地代码集成到我的项目中。为此,我使用新的Pigeon包:https://pub.dev/packages/pigeon

在安卓上它工作得很好,但是在iOS上,每当我试图调用用swift编写的方法(按下按钮时)时,它抛出一个通道错误(PlatformException-error,Unable to establish connection On channel.,null,null)

我已经设置了flutter启动项目,然后当按下floatingActionButton时,我将调用本机方法。当执行本机方法时,它会在Android端返回一个字符串"Hello from Android“,并在iOS上返回"Hello from Xcode”。

main.dart文件:

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:platforms/pigeon.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          Api api = Api();
          final searchReply = await api.search(SearchRequest());
          print(searchReply.result);
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

MainActivity.java文件:

代码语言:javascript
复制
package com.example.platforms;
import android.os.Bundle;
import io.flutter.embedding.android.FlutterActivity;

public class MainActivity extends FlutterActivity {
    private class Api implements Pigeon.Api {

        @Override
        public Pigeon.SearchReply search(Pigeon.SearchRequest arg) {
            Pigeon.SearchReply searchReply = new Pigeon.SearchReply();
            searchReply.setResult("Hello from Android!");
            return searchReply;
        }
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Pigeon.Api.setup(getFlutterEngine().getDartExecutor().getBinaryMessenger(), new Api());
    }
    
}

AppDelegate.swift文件:

代码语言:javascript
复制
import UIKit
import Flutter




@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, Api {
    var engine: FlutterEngine = {
        let result = FlutterEngine.init()
        // This could be `run` earlier in the app to avoid the overhead of doing it the first time the
        // engine is needed.
        result.run()
        return result
      }()
    
    
    func search(_ input: SearchRequest, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) -> SearchReply? {
        
        let reply = SearchReply()
        
        reply.result = "Hello from Xcode!!!!"
        return reply
    }
    
    
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    
    GeneratedPluginRegistrant.register(with: self)
    ApiSetup(engine.binaryMessenger, self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

在安卓系统上运行onPressed的结果:

在iOS上执行onPressed的结果:

同样值得注意的是,当我在didChangedDependencies函数中调用onPressed中的代码时,swift中的代码确实会运行,结果也会显示出来,但随后会再次抛出相同的异常。这意味着通道确实被创建了,我只是错误地使用了它。

当它被添加到main.dart时

代码语言:javascript
复制
@override
  void didChangeDependencies() async {
    Api api = Api();
    final searchReply = await api.search(SearchRequest());
    print(searchReply.result);
    super.didChangeDependencies();
  }

它打印来自swift的结果,然后抛出相同的错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-05 02:50:23

我认为BinaryMessenger设置得不正确。

我尝试过这样做,它起作用了:在didFinishLaunchingWithOptions方法中,获取rootViewController并将其转换为FlutterBinaryMessenger

代码语言:javascript
复制
let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
// get binaryMessenger
let binaryMessenger = rootViewController as! FlutterBinaryMessenger
    
// set binaryMessenger
ApiSetup(binaryMessenger, self)

完整的方法如下所示:

代码语言:javascript
复制
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self);
    
    let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
    
    // get binaryMessenger
    let binaryMessenger = rootViewController as! FlutterBinaryMessenger
    
    // set binaryMessenger
    ApiSetup(binaryMessenger, self)

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68246158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档