如何在Swift中编写Cordova插件?

如何在Swift中编写Cordova插件?,cordova,swift,Cordova,Swift,我将现有自定义插件转换为Swift语言: (位于插件/custompluginswift.swift下) 我有两个问题: CDVPlugin未找到 Javascript没有看到插件:custompluginswift: CDVPlugin类CustomPluginInSwift(pluginName:CustomPluginInSwift)不存在 我留下了相同的config.xml,但它没有按预期工作 我的问题在哪里 CDVPlugin未找到 当您第一次创建swift文件时,Xcode要求您

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

(位于
插件/custompluginswift.swift
下)

我有两个问题:

  • CDVPlugin
    未找到
  • Javascript没有看到插件:
    custompluginswift
CDVPlugin类CustomPluginInSwift(pluginName:CustomPluginInSwift)不存在

我留下了相同的
config.xml
,但它没有按预期工作

我的问题在哪里

CDVPlugin
未找到

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

-桥接头.h
带有空内容的头:

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
在此标题中添加:

#import <Cordova/CDVPlugin.h>
如何知道什么是合适的索引

[步骤2]

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

var temp:CustomPluginInSwift = CustomPluginInSwift()
,Swift将向
-Swift.h
标题添加新类名。问题是在项目中看不到此标题

如何找到它?

  • 转到xCode->Window->Organizer->“项目选项卡”
  • 选择您的项目
  • 复制“派生数据”路径(对于我来说:
    ~/Library/Developer/Xcode/DerivedData/-hbgwavxfqvhwxzagxhgzjvsdrkjk
  • 转到控制台并运行
    cd~/Library/Developer/Xcode/DerivedData/-hbgwavxfqvhwxzagzjvsdrkjk
  • 运行之后:
    cd Build/Intermediates/.Build/Debug iphoneos/.Build/DerivedSources/
您可以在那里找到名为:
-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

/* ... */
@objc(HWPMyPlugin) class MyPlugin : CDVPlugin { // see @tsubik answer
 /* ... */
}
因此我们得到了正确的名称:
\u TtC8Wanameet14CustomPluginInSwift

[步骤3]

现在,转到
config.xml
并更改为:

<feature name="CustomPluginInSwift">
    <param name="ios-package" value="CustomPluginInSwift" />
</feature>
解析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并在一段时间后返回答案的方法示例:

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

}
当您尝试通过异步方式在本机端获取一些数据时,我使用了很多这种方法:

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


}

如上所述,您必须添加一个桥接头.h文件,其中包含

#import <Cordova/CDV.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>


我认为它是更好的解决方案。应该注意的是,当前的Cordova版本(4.3.0)似乎没有生成与Swift兼容的XCode项目。如果您使用的是Cordova CLI,则可能需要下载边缘版本以使项目正确生成。请参阅:目前我正在使用钩子在xCode项目中启用swift支持。很高兴知道他们正在使用内置解决方案。我在这里编写了关于如何使用最新的XCode 8.2/Swift 3执行此操作的教程:还要确保在Swift方法定义之前添加
@objc(getSettings:)
!否则,您必须将js中的操作标记为“getSettingsCommand”
your-app-name/plugins/com.plugin.example/bridging-header.h
@objc(HWPCustomPluginInSwift) class CustomPluginInSwift : CDVPlugin {
<feature name="CustomPluginInSwift">
    <param name="ios-package" value="HWPCustomPluginInSwift" />
</feature>