How can I use a UIKit ViewController inside Flutter Plugin code? - flutter

I'm trying to use UIDocumentPickerViewController in the same way as this documentation. When I try to use the example code in the plugin, I get the following errors:
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: No exact matches in call to initializer
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: Found candidate with type '([URL]) -> UIDocumentPickerViewController'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:15: Found candidate with type '([URL]) -> UIDocumentPickerViewController'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:16:72: Type 'Array<URL>.ArrayLiteralElement' (aka 'URL') has no member 'folder'
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:21:41: Cannot find 'startingDirectory' in scope
flutter_download_manager_darwin/ios/Classes/SwiftFlutterDownloadManagerDarwinPlugin.swift:25:11: Cannot find 'present' in scope
Here is the exact code:
import Flutter
import UIKit
public class SwiftFlutterDownloadManagerDarwinPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_download_manager_darwin", binaryMessenger: registrar.messenger())
let instance = SwiftFlutterDownloadManagerDarwinPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: #escaping FlutterResult) {
switch call.method {
case "pickDirectoryUrl":
// Create a document picker for directories.
let documentPicker =
UIDocumentPickerViewController(forOpeningContentTypes: [.folder])
documentPicker.delegate = self
// Set the initial directory.
documentPicker.directoryURL = startingDirectory
// Present the document picker.
present(documentPicker, animated: true, completion: nil)
default:
result(FlutterMethodNotImplemented)
}
}
}

init(forOpeningContentTypes:) is supported in iOS 14.0+, while most likely the minimum iOS version that your app supports is lower.

Related

How can i connect Swift file and dart file?

I`m connecting Flutter and Swift so that i can use it in Flutter by connecting the public certificate api that works only in Swift. but, I have an issue and i want to ask a question.
What i want to do is import a Swift function through a channel to main.dart so that Swift code can work when a button is pressed in main.dart
How can i get func in Tilko.swift to main.dart
Here is that Structures
enter image description here
main.dart is in ios/lib folder and Tilko.swift is in ios/Runner
There should be a FlutterMethodChannel.swift
and it look like
class MethodChannelFlutter {
var controller: FlutterViewController
var printerChannel: FlutterMethodChannel
init(controller: FlutterViewController) {
self.controller = controller
printerChannel = FlutterMethodChannel(name: "hem_cert_copy_plugin", binaryMessenger: controller.binaryMessenger)
printerChannel.setMethodCallHandler {
(call: FlutterMethodCall, _: #escaping FlutterResult) -> Void in
//Your handler
//...
and your AppDelegate.swift should be like
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
MethodChannelFlutter(controller: controller)
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
I have create a working sample here
https://github.com/theamorn/flutter-template
In this file, I have 3 ways of connecting to Native SDK
calling Native and return value immediately
calling Native and pass to function and return from that function
calling Native and wait for the delegate to callback so we can callback to Flutter
First you add Flutter Channel in iOS
https://github.com/theamorn/flutter-template/blob/main/ios/Runner/AppDelegate.swift
private func initFlutterChannel() {
// com.theamorn.flutter can change to whatever you want, just have to be the same between Flutter and iOS and unique ‘domain prefix. just com.theamorn is not enough
if let controller = window?.rootViewController as? FlutterViewController {
let channel = FlutterMethodChannel(
name: methodChannel,
binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ [weak self] (
call: FlutterMethodCall,
result: #escaping FlutterResult) -> Void in
switch call.method {
case "methodNameOne":
if let data = call.arguments as? String {
self?.callNativeSDK(data)
} else {
result(FlutterMethodNotImplemented)
}
case "deviceHasPasscode":
result(self?.isDeviceHasPasscode)
case "returnValue":
if let data = call.arguments as? String {
self?.returnValueSDK(result: result, id: data)
} else {
result(FlutterMethodNotImplemented)
}
default:
result(FlutterMethodNotImplemented)
}
})
}
}
methodNameOne use for calling Native function with a delegate which name should be consistent within Flutter
private func callNativeSDK(_ id: String) {
// You can put any Native SDK in here, if the result return from Delegate
let sdk = ThirdPartySDK(delegate: self, id: id)
sdk.start()
}
private func returnValueSDK(result: FlutterResult, id: String) {
// You can call any SDK in here if the result return immediately
let sdk = ThirdPartySDK(delegate: self, id: id)
return result(sdk.process())
}
To call from Flutter using this
https://github.com/theamorn/flutter-template/blob/main/lib/main.dart
final channel = MethodChannel('com.theamorn.flutter');
try {
await channel.invokeMethod('methodNameOne', "12345");
} on PlatformException catch (e) {
debugPrint("==== Failed to get data '${e.message}' ====");
}
Calling back from Native to Flutter, I call this function in Delegate of mocking SDK
extension AppDelegate: ThirdPartySDKDelegate {
func onFinish(value: String) {
// You can send anything into arguments, String, Boolean, or even Dictionary
// Send data back to Flutter
if let controller = self.window?.rootViewController as? FlutterViewController {
let channel = FlutterMethodChannel(
name: methodChannel,
binaryMessenger: controller.binaryMessenger)
channel.invokeMethod("methodNameTwoFromSDK", arguments: value)
}
}
}
Waiting Value from Native
_waitingDataFromNative() async {
channel.setMethodCallHandler((call) async {
// Receive data from Native
switch (call.method) {
case "methodNameTwoFromSDK":
_nativeValue = call.arguments;
setState(() {});
break;
default:
break;
}
});
}
You see that method name in iOS, and Flutter needs to be exactly the same otherwise they can't see each others.

Singleton not accessible in Sirikit IntentHandler

I have a project that I want to add sirikit to. I added the intent and wanted to store values in my datastorage which is realm, when I tried to access the function that is used to create this task , I get an eeror. this is my code below
extension IntentHandler : INCreateTaskListIntentHandling {
public func handle(intent: INCreateTaskListIntent,
completion: #escaping (INCreateTaskListIntentResponse) -> Swift.Void) {
guard let title = intent.title else {
completion(INCreateTaskListIntentResponse(code: .failure, userActivity: nil))
return
}
CategoryFunctions.instance.createList(name: title.spokenPhrase,.....)
var tasks: [INTask] = []
if let taskTitles = intent.taskTitles {
let taskTitlesStrings = taskTitles.map {
taskTitle -> String in
return taskTitle.spokenPhrase
}
tasks = createTasks(fromTitles: taskTitlesStrings)
CategoryFunctions.instance.add(tasks: taskTitlesStrings, toList: title.spokenPhrase)
}
let response = INCreateTaskListIntentResponse(code: .success, userActivity: nil)
response.createdTaskList = INTaskList(title: title,
tasks: tasks,
groupName: nil,
createdDateComponents: nil,
modifiedDateComponents: nil,
identifier: nil)
completion(response)
}
}
this singlton instantiation works well in my app but I do not know why I get an error saying Use of unresolved identifier 'CategoryFunctions'
my CategoryFunctions singleton
class CategoryFunctions {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var database:Realm!
static let instance = CategoryFunctions()
.....
...
Select your file in xcode, on the right, choose the File Inspector, then under Target Membership, pick your Intent.

Swift closure using firebase blocks compile

I'm following an online class (from December, 2016) and am getting the error in this screenshot.
Here's my code:
//
// FirebaseManager.swift
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseAuth
import FirebaseAnalytics
class FirebaseManager: NSObject {
static let databaseRef = FIRDatabase.database().reference()
static var currentUserId:String = ""
static var currentUser:FIRUser? = nil
static func Login(email:String, password:String, completion: #escaping (_ success:Bool) ->
Void) {
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user,error)
in
if let error = error {
print(error.localizedDescription)
completion(false)
} else {
curentUser = user
currentUserId = (user?.uid)!
completion(true)}
})
}
}
And here is the screenshot of the code from this example:
I've reviewed a few SO questions including this one but don't see an answer that applies to my situation.
Please see my attachedmy swift version settings swift settings. Attaching again as I don't see it.
Thanks for your help
Why are you using legacy Swift instead of Swift 3? The sample code you show is for Swift 3. The #escaping attribute was introduced in Swift 3, so that could explain the build error.

Swift 3: fix issue Type "className" does not conform to protocol 'UIDocumentPickerDelegate'

I'm migrating my code from Swift 2 to Swift 3 but my code throws this error: Type "className" does not conform to protocol 'UIDocumentPickerDelegate'. I've migrate many parts of my document as you can see but error stills,
extension className: UIDocumentMenuDelegate {
//Opening the Document Menu
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
print ("documentMenu")
self.present(documentPicker, animated: true, completion: nil)
}
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController) {
}
}
//Using UIDocumentPickerDelegate, error persists here.
extension className: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
if(controller.documentPickerMode == UIDocumentPickerMode.import){
print ("success")
}
}
}
class className: BaseViewController{
...Tons of code here...
#IBAction func importKeyButtonPressed(_ sender: UIButton) {
let importMenu = UIDocumentMenuViewController(documentTypes: ["public.data","public.text","public.content"], in: UIDocumentPickerMode.import)
var documentPicker = UIDocumentPickerViewController(documentTypes: ["public.txt"], in: UIDocumentPickerMode.import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = UIModalPresentationStyle.fullScreen
self.present(documentPicker, animated: true, completion: nil)
}
How can I solve it?, I've use all methods that procotol requires. Thanks
I revised your information on this link that has a similar problem.
Cannot conform to STPAddCardViewControllerDelegate since Xcode 8 GM on Swift 3
The problem is the swift compiler than can´t recognize automatically some information. So in this case:
didPickDocumentAt url: URL
Then i follow the problem to this link:
https://bugs.swift.org/browse/SR-2596
In this link the information is that Swift 3 mistake data types, so i research some more and get to this page. The mistaken type in this case is "URL".
Then the solution is in the same page. I write it bellow:
weak var delegate : UIDocumentPickerDelegate?
#available(iOS 8.0, *)
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: Foundation.URL ){
//
print("something")
}
To that matter i reproduce the error in my computer, it is caused when diferent imported libraries has the same definition for data types, in this case URL type, which Swift 3 doesnt recognize automatically neither tells correctly the error. So it has to be defined directly.

Alamofire: Cannot call value of non-function type 'NSHTTPURLResponse?'

I have an extension on a class called APIManager:
import Alamofire
import Foundation
// MARK: - Logout
extension APIManager {
public func performLogout() {
let request = defaultManager.request(APIManager.Router.Logout.URLRequest)
request.response( // ERROR ON THIS LINE AS NOTED BELOW
queue: APIManager.responseQueue,
responseSerializer: Request.stringResponseSerializer(),
completionHandler: { [weak self] (response) in
guard let strongSelf = self else { return }
}
)
}
}
When the extension is included underneath the APIManager class in the SAME FILE, there is no issue whatsoever.
However, when I take the extension and move it into a NEW FILE, I receive this error:
Cannot call value of non-function type 'NSHTTPURLResponse?'
It's obvious that when the extension is placed in another file, the compiler is confusing the method above as defined Alamofire/ResponseSerialization.swift with the 'response' property in Alamofire/Request.swift of the Alamofire Request class
The APIManager class is below:
public final class APIManager {
// MARK: - Singleton shared instance
static let sharedInstance = APIManager()
let defaultManager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"TBD1": .PinCertificates(
certificates: ServerTrustPolicy.certificatesInBundle(),
validateCertificateChain: true,
validateHost: true
),
"TBD2": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
}
There is a similar question here but it's not quite the same:
Cannot call value of non-function type 'NSHTTPURLResponse?' Alamofire ObjectMapper
If this is, as you say, working fine in the other file a couple of suggestions come to mind.
Mark the class you are extending as public. (Swift classes are internal by default.)
Open the document inspector pane on the right of your class, make sure your target membership includes the target you are compiling for.
Let me know if your issue still persists and I will investigate further.