I converted existing custom plugin to Swift language:
(located under Plugins/CustomPluginInSwift.swift
)
import Foundation
class Cu
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)
}
}
}
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>