Подтвердить что ты не робот

Как написать плагин 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 то же самое, но он не работает должным образом.

Где моя проблема?

4b9b3361

Ответ 1

Как уже упоминалось, вы должны добавить файл моста-header.h, содержащий

#import <Cordova/CDV.h>

Также вам нужно добавить заголовок заголовка моста в свойствах проекта XCode- > Настройки сборки → Objective-C Мостовой заголовок. Например:

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

Кроме того, для того, чтобы Objective-C увидеть одно имя класса плагина, вам нужно добавить сопоставление @objc в объявление класса. Это может быть то же самое, что и название самого быстрого класса, или что-то другое. В этом примере "HWPCustomPluginInSwift" будет тем, что Objective-C (и Javascript) в конечном итоге увидит:

@objc(HWPCustomPluginInSwift) class CustomPluginInSwift : CDVPlugin {

а затем ваша функция node в файле config.xml должна выглядеть так:

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

Ответ 2

CDVPlugin не найден

Когда вы создали быстрый файл в первый раз, Xcode попросит вас сгенерировать

<your app name>-Bridging-Header.h заголовок с пустым контентом:

//
//  Use this file to import your target 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 → Окно → Органазер → "Вкладки проекта"
  • Выберите свой проект
  • копировать путь "Производные данные" (для меня: ~/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 в вашем проекте (созданная Кордовой).

Мы создаем новый быстрый файл 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 и через некоторое время возвращаем ответ:

Я использовал эту форму метода, когда вы пытаетесь получить некоторые данные на собственной стороне с помощью async:

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


}