I converted existing custom plugin to Swift language:
(located under Plugins/CustomPluginInSwift.swift
)
import Foundation class CustomPluginInSwift : CDVPlugin { func getSettings(command: CDVInvokedUrlCommand) { println("CustomPluginInSwift :: getSettings is called") var pluginResult = CDVPluginResult(status: CDVCommandStatus_OK) commandDelegate.sendPluginResult(pluginResult, callbackId:command.callbackId) } }
And I have two problems:
CDVPlugin
not foundCustomPluginInSwift
:CDVPlugin class CustomPluginInSwift (pluginName: CustomPluginInSwift) does not exist
I left config.xml
the same but it doesn't work as expected.
Where is my problem?
This Cordova plugin adds the Swift support to your iOS project.
As is mentioned you have to add a bridging-header.h file which contains
#import <Cordova/CDV.h>
Also you need to add the bridging header's path in XCode project properties->Build Settings->Objective-C Bridging Header. For example:
your-app-name/plugins/com.plugin.example/bridging-header.h
Additionally, in order for Objective-C to see the same plugin class name, you need to add an @objc mapping to the class declaration. It can be the same as the swift class name itself, or something different. In this example, "HWPCustomPluginInSwift" will be what Objective-C (and Javascript) will end up seeing:
@objc(HWPCustomPluginInSwift) class CustomPluginInSwift : CDVPlugin {
and then your feature node in config.xml file should look like this:
<feature name="CustomPluginInSwift"> <param name="ios-package" value="HWPCustomPluginInSwift" /> </feature>
CDVPlugin
not found
When you created swift file 1st time, Xcode asks you to generate
<your app name>-Bridging-Header.h
header with empty content:
// // Use this file to import your target's public headers that you would like to expose to Swift. //
In this header add:
#import <Cordova/CDVPlugin.h>
After that clean your project. If you don't have this header - create it.
CDVPlugin class CustomPluginInSwift (pluginName: CustomPluginInSwift) does not exist
[Step 1]
Right, because Swift uses _TtC
(Type To Class) prefix and class index with following template:
_TtC8<AppName><index#><PluginName>
How to know what is proper index?
[Step 2]
When you initiate instance of CustomPluginInSwift
class, like:
var temp:CustomPluginInSwift = CustomPluginInSwift()
, Swift will add new class name to <AppName>-Swift.h
header. The problem is that this header you can't see in your project.
How to find it?
~/Library/Developer/Xcode/DerivedData/<AppName>-hbgwavxfqvhwxzagxhgzjvsdrkjk
)cd ~/Library/Developer/Xcode/DerivedData/<AppName>-hbgwavxfqvhwxzagxhgzjvsdrkjk
cd Build/Intermediates/<App name>.build/Debug-iphoneos/<App name>.build/DerivedSources/
You can find file named: <App name>-Swift.h
there with following content:
/* ... */ SWIFT_CLASS("_TtC8Wanameet14CustomPluginInSwift") @interface CustomPluginInSwift : CDVPlugin - (void)getSettings:(CDVInvokedUrlCommand *)command; - (instancetype)initWithWebView:(UIWebView *)theWebView OBJC_DESIGNATED_INITIALIZER; - (instancetype)init OBJC_DESIGNATED_INITIALIZER; @end /* ... */
So we got proper name: _TtC8Wanameet14CustomPluginInSwift
[Step 3]
Now, go to config.xml
and change from:
<feature name="CustomPluginInSwift"> <param name="ios-package" value="CustomPluginInSwift" /> </feature>
to:
<feature name="MeeterCalendar"> <param name="ios-package" value="_TtC8Wanameet14CustomPluginInSwift" /> </feature>
Thats all,
Hope it will save time,
tested on cordova 3.5
+ xCode6.1
Consider you have Plugins
folder in your project (generated by Cordova).
We create New swift file MyPlugin.swift
with following content:
@objc(HWPMyPlugin) class MyPlugin : CDVPlugin { // see @tsubik answer /* ... */ }
method example where we parse javascript request and immediately return answer:
func someMethod(command: CDVInvokedUrlCommand){ println("MyPlugin :: someMethod is called") let callbackId:String = command.callbackId var obj:AnyObject = command.arguments[0] as AnyObject! var eventStructure:AnyObject = obj["eventStructure"] var eventId:String = eventStructure["_id"] as AnyObject! as String println("MyPlugin :: someMethod :: _id: \(eventId) ") self.commandDelegate.runInBackground({ // 'jw' is some class var data:NSData = jw.toJson() var str:String = jw.toJsonString(data) var obj:JSONObject = jw.getJSONObjectFromNSData(data) println("sampleList as String: \(str)") var pluginResult:CDVPluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAsDictionary: obj) self.commandDelegate.sendPluginResult(pluginResult, callbackId:command.callbackId) }) }
method example where we return empty callabck and after some time return answer:
I used a lot this method form when you try to fetch some data on native side by async way:
protocol AccountLoaderListenerItf { func onAccountsDone(data:NSData) } @objc(HWPMyPlugin) class MyPlugin : CDVPlugin, AccountLoaderListenerItf { var mCalendarAccountsCallbackContext:String? func getCalendarAccounts( command: CDVInvokedUrlCommand ){ println("MyPlugin :: getCalendarAccounts is called") self.mCalendarAccountsCallbackContext = command.callbackId self.commandDelegate.runInBackground({ var all:AccountLoaderListenerItf = self var accounts = MyAccounts(accLoader: all) accounts.populateFromCalendars() var pluginResult:CDVPluginResult = CDVPluginResult(status:CDVCommandStatus_NO_RESULT) pluginResult.setKeepCallbackAsBool(true) self.commandDelegate.sendPluginResult(pluginResult, callbackId:command.callbackId) }) } // func /* .... */ func onAccountsDone(data:NSData){ if self.mCalendarAccountsCallbackContext != nil { var list:JSONArray = WmUtils.getJSONArrayFromNSData(data) // dummy data var pluginResult:CDVPluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAsArray: list) pluginResult.setKeepCallbackAsBool(false) self.commandDelegate.sendPluginResult(pluginResult, callbackId:self.mCalendarAccountsCallbackContext) } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With