Flutter - How to invoke channel in native Swift code? - ios

I have written native Swift code in my AppDelegate, I am trying to invoke a third party sdk callback in my dart side of code, however the declaration of my method channel can only be done in application function. How do I invoke a channel in my delegate methods to make a dart callback?
import UIKit
import Flutter
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate, TJPlacementDelegate {
public func requestDidSucceed(_ placement: TJPlacement!) {
//Need to invoke methodChannel here
}
public func requestDidFail(_ placement: TJPlacement!, error: Error!) {
//Need to invoke methodChannel here
}
public func contentIsReady(_ placement: TJPlacement!) {
//Need to invoke methodChannel here
}
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let channelName = "ios_native"
let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: rootViewController as! FlutterBinaryMessenger)
methodChannel.setMethodCallHandler {(call: FlutterMethodCall, result: FlutterResult) -> Void in
switch(call.method) {
case "setDebugEnabled":
let isDebug = call.arguments as! Bool
Tapjoy.setDebugEnabled(isDebug)
break;
default: result(FlutterMethodNotImplemented)
}
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
I can't declare my methodChannel outside my application as the window doesn't get recognised.

Define the method channel in the AppDelegate:
var methodChannel: FlutterMethodChannel!
Initialize it:
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
...
methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: rootViewController as! FlutterBinaryMessenger)
}
Now you can call invokeMethod:
public func requestDidSucceed(_ placement: TJPlacement!) {
methodChannel.invokeMethod()
}

Related

Platform Method Channel From iOS Side to Flutter

so i have an issue when trying to implement the platform method channel for my flutter project, When i try to invoke a method from flutter to ios side, it gets triggered and everything is working perfectly but when i try to invoke a method from ios side (appDelegate file) to flutter in order to perform a sepecific task, it's not working.
AppDelegate.swift Code:
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
application.registerForRemoteNotifications()
GeneratedPluginRegistrant.register(with: self)
let controller = (window?.rootViewController as! FlutterViewController)
let methodChannle = FlutterMethodChannel(name: "channelMethodTest", binaryMessenger: controller.binaryMessenger)
methodChannle.invokeMethod("taskName", arguments: [:])
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
Flutter main.dart:
const methodChannel = MethodChannel('channelMethodTest');
Future<void> methodHandler(MethodCall call) async {
final String idea = call.arguments;
switch (call.method) {
case "taskName":
print(
"receiving task from ios to flutter");
break;
default:
print('no method handler for method ${call.method}');
}
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
methodChannel.setMethodCallHandler(methodHandler);
}
I tried searching for tutos on how to do it but i cannot find any
you need to make the channelmethod var global then you need to instantiate the method channel in the didFinishLaunchingWithOptions func if you're using the method channel to invoke any method in the app deletage or any extension related to it.
Ensure that the channel name is the same in Flutter and iOS side. Now they seem to be different:
let methodChannle = FlutterMethodChannel(name: "channelMethodTest", binaryMessenger: controller.binaryMessenger)
const methodChannel = MethodChannel('beyang.com-channelMethodTest');

Flutter cannot call result in native ios code

Good day, maybe someone can help me here. I have a SDK built into Flutter that I call via the ChannelMethod. There I enter a callback whose result I want to give back to flutter. The callback works but for some unknown reason the result function is not triggered.
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let testChannel = FlutterMethodChannel(name: "test",
binaryMessenger: controller.binaryMessenger)
testChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "startProcess" else {
result(FlutterMethodNotImplemented)
return
}
let args = call.arguments as! Dictionary<String, Any>
let mainVC = ViewController()
mainVC.callBack = { (resultValue: String) in
print("Callback called:")
print(resultValue)
// <-------- this does not work -------->
result(resultValue)
result("test")
};
mainVC.caseId = args["caseId"] as! String
let navigationController = UINavigationController(rootViewController: mainVC)
self?.window.rootViewController = navigationController
self?.window.makeKeyAndVisible()
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

Flutter iOS native navigation

I currently have the problem that I don't know how to give native a screen in iOS a callback function and a string.
It is currently implemented as follows:
import UIKit
import Flutter
import PostidentSDK
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let kycChannel = FlutterMethodChannel(name: "kyc",
binaryMessenger: controller.binaryMessenger)
kycChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "startProcess" else {
result(FlutterMethodNotImplemented)
return
}
let mainVC = ViewController() // Your viewController
let navigationController = UINavigationController(rootViewController: mainVC)
self?.window.rootViewController = navigationController
self?.window.makeKeyAndVisible()
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
someFunction()
}
}
The Screen ViewController is then called and on this I want to have the string caseId & then execute the Flutter result there and close the screen.

Run a Swift UI Page from Flutter AppDelegate.swift file

I want to run a custom Swift UI page in my flutter application. I am trying to call ios platform specific code using method channel. My target is when i call a method using method channel i will present the Swift UI view in front of user.
My AppDelegate.swift file is below:
import UIKit
import Flutter
#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: "yourpackageName/channelName",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
if call.method == "showPage"{
//run a swift ui view here
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
And my custom Swift UI file is below:
import SwiftUI
#available(iOS 13.0, *)
struct CustomPage: View {
var body: some View {
Text("Hello, World!")
}
}
#available(iOS 13.0, *)
struct CustomPage_Previews: PreviewProvider {
static var previews: some View {
CustomPage()
}
}
Is there any way i can achieve this?

how to implement protocol delegate pattern in App Delegate when using Platform Specific code in Flutter?

I want to implement platform specific code for my Flutter app on iOS. I want to implement EventKit from native iOS. but now I am confused how to implement protocol delegate pattern in the app delegate when using Platform Channel in Flutter.
in native iOS, my code will be like this
import EventKitUI
class MyViewController : UIViewController, EKEventEditViewDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonPressed(_ sender: Any) {
// after pressing a button then show a VC
showEventKitViewController()
}
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
// this is the method to conform the protocol
dismiss(animated: true, completion: nil)
}
func showEventKitViewController() {
let eventVC = EKEventEditViewController()
eventVC.editViewDelegate = self // I am confused in this line
eventVC.eventStore = EKEventStore()
let event = EKEvent(eventStore: eventVC.eventStore)
eventVC.event = event
present(eventVC, animated: true)
}
}
as you can see, I assign self ( MyViewController class as the delegate ) for editViewDelegate
now I am confused how to implement showEventKitViewController method above in Flutter app delegate below
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "useOtherApp", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) -> Void in
if (call.method == "saveToEventKit") {
// what should I do in here to get the same result like my code above in native?
}
})
}
especially when I need to assign a class as the delegate for editViewDelegate like this
I can solve it by using the code like this by using extension. please scroll to the very bottom to see FlutterViewController extension
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
setUpMethodChannels(controller: controller) // set the method channel
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func setUpMethodChannels(controller: FlutterViewController) {
let channel = FlutterMethodChannel(name: "useOtherApp", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) -> Void in
guard let args = call.arguments as? [String : Any] else {return}
if (call.method == "saveToCalendar") {
let eventVC = EKEventEditViewController()
eventVC.editViewDelegate = controller // set FlutterViewController as the delegate
eventVC.eventStore = EKEventStore()
let event = EKEvent(eventStore: eventVC.eventStore)
eventVC.event = event
eventVC.title = "hallooooo"
controller.present(eventVC, animated: true)
} else {
result(FlutterMethodNotImplemented)
}
})
}
}
// set the extension like below OUTSIDE the AppDelegate class
extension FlutterViewController : EKEventEditViewDelegate, UINavigationControllerDelegate {
// conform to the EKEventEditViewDelegate protocol
public func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
dismiss(animated: true, completion: nil)
}
}

Resources