Flutter iOS native navigation - ios

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.

Related

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)
}
}

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)
}
}

Flutter - How to invoke channel in native Swift code?

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()
}

ViewController not changing after first time use

Hi I want to show a view controller only at the first use (i.e: the first time someone starts the app up and never again).
I think I have the right code but for some reason it's just not working. Does anyone know why?
AppDelegate.swift
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let userDefaults = UserDefaults.init()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
userDefaults.set(true, forKey: "isFirstTime")
userDefaults.set("RealmNotChosenOrSuggested", forKey: "RegionPreference")
userDefaults.set([], forKey: "PreferredRealms")
// Not using Storyboard instantiation code
window = UIWindow(frame:UIScreen.main.bounds) //canvas
window?.makeKeyAndVisible()
if (userDefaults.bool(forKey: "isFirstTime")){
userDefaults.set(false, forKey: "isFirstTime")
window?.rootViewController = StartupViewController()
} else{
window?.rootViewController = DashboardViewController()
}
return true
}
StartupViewController.swift
class StartupViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
DashboardViewController.swift
import UIKit
class DashboardViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
}
Because every time app opens this runs you overwrite the key isFirstTime in the first line
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// userDefaults.set(true, forKey: "isFirstTime") // firs line comment it
if !(userDefaults.bool(forKey: "isFirstTime")){
userDefaults.set(true, forKey: "isFirstTime")
userDefaults.set("RealmNotChosenOrSuggested", forKey: "RegionPreference")
userDefaults.set([], forKey: "PreferredRealms")
window?.rootViewController = StartupViewController()
} else{
window?.rootViewController = DashboardViewController()
}

Resources