如何在Swift中编写Cordova插件?

时间:2014-08-22 14:08:47

标签: cordova swift

我将现有的自定义插件转换为Swift语言:

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

我有两个问题:

  • CDVPlugin未找到
  • Javascript没有看到插件:CustomPluginInSwift
  

CDVPlugin类CustomPluginInSwift(pluginName:CustomPluginInSwift)不存在

我离开了config.xml,但它没有按预期工作。

我的问题在哪里?

2 个答案:

答案 0 :(得分:27)

如前所述,您必须添加包含

的bridging-header.h文件
#import <Cordova/CDV.h>

此外,您还需要在XCode项目属性中添加桥接头路径 - > Build Build-&gt; Objective-C Bridging Header。例如:

your-app-name/plugins/com.plugin.example/bridging-header.h

此外,为了让Objective-C看到相同的插件类名,您需要将@objc映射添加到类声明中。它可以与swift类名本身相同,也可以是不同的名称。在这个例子中,“HWPCustomPluginInSwift”将是Objective-C(和Javascript)最终会看到的内容:

@objc(HWPCustomPluginInSwift) class CustomPluginInSwift : CDVPlugin {

然后config.xml文件中的功能节点应如下所示:

<feature name="CustomPluginInSwift">
    <param name="ios-package" value="HWPCustomPluginInSwift" />
</feature>

答案 1 :(得分:10)

  

CDVPlugin未找到

第一次创建swift文件时,Xcode会要求您生成

带有空内容的

<your app name>-Bridging-Header.h标题:

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//

在此标题中添加:

#import <Cordova/CDVPlugin.h>

之后清理您的项目。如果您没有此标题 - 请创建它。


  

CDVPlugin类CustomPluginInSwift(pluginName:CustomPluginInSwift)不存在

[第1步]

是的,因为Swift使用_TtC Type To Class )前缀和类索引以及以下模板:

_TtC8<AppName><index#><PluginName>   

如何知道什么是正确的索引?

[第2步]

当您启动CustomPluginInSwift类的实例时,例如:

var temp:CustomPluginInSwift = CustomPluginInSwift()

,Swift会将新的类名添加到<AppName>-Swift.h标题中。问题是你在项目中看不到这个标题。

如何找到它?

  • 转到xCode - &gt;窗口 - &gt; Organazer - &gt; “项目标签”
  • 选择您的项目
  • 复制“派生数据”路径(对我来说:~/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/

您可以在其中找到名为<App name>-Swift.h的文件,其中包含以下内容:

/* ... */

SWIFT_CLASS("_TtC8Wanameet14CustomPluginInSwift")
@interface CustomPluginInSwift : CDVPlugin
- (void)getSettings:(CDVInvokedUrlCommand *)command;
- (instancetype)initWithWebView:(UIWebView *)theWebView OBJC_DESIGNATED_INITIALIZER;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

/* ... */

所以我们得到了正确的名字:_TtC8Wanameet14CustomPluginInSwift

[第3步]

现在,转到config.xml并从:

更改
<feature name="CustomPluginInSwift">
    <param name="ios-package" value="CustomPluginInSwift" />
</feature>

为:

<feature name="MeeterCalendar">
    <param name="ios-package" value="_TtC8Wanameet14CustomPluginInSwift" />
</feature>

多数,

希望能节省时间,

cordova 3.5 + xCode6.1

上进行了测试

实施例

考虑项目中有Plugins文件夹(由Cordova生成)。

我们使用以下内容创建新的swift文件MyPlugin.swift

@objc(HWPMyPlugin) class MyPlugin : CDVPlugin { // see @tsubik answer
 /* ... */
}

我们解析javascript请求并立即返回答案的方法示例:

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

}

方法示例我们返回空的callabck并在一段时间后返回答案:

当您尝试通过异步方式在本机端获取某些数据时,我使用了很多此方法表单:

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


}