Comment écrire Cordova plugin dans Swift?

J'ai converti le plugin personnalisé existant en langage Swift:

(situé en vertu de 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)
    }
}

Et j'ai deux problèmes:

  • CDVPlugin non trouvé
  • Javascript ne voit pas le plugin: CustomPluginInSwift:

La classe CDVPlugin CustomPluginInSwift (pluginName: CustomPluginInSwift) n'existe pas

J'ai quitté config.xml la même chose mais cela ne fonctionne pas comme prévu.

Où est mon problème?

21
demandé sur Maxim Shoustin 2014-08-22 18:08:47

2 réponses

Comme il est mentionné, vous devez ajouter un en-tête de pontage.h fichier qui contient

#import <Cordova/CDV.h>

Vous devez également ajouter le chemin de l'en-tête de pontage dans Xcode project properties->Build Settings->Objective-C Bridging Header. Par exemple:

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

De plus, pour que Objective-C puisse voir le même nom de classe de plugin, vous devez ajouter un mappage @ objc à la déclaration de classe. Cela peut être le même que le nom de classe swift lui-même, ou quelque chose de différent. Dans cet exemple, "HWPCustomPluginInSwift" sera ce que Objective - C (et Javascript) finira par voir:

@objc(HWPCustomPluginInSwift) class CustomPluginInSwift : CDVPlugin {

Puis votre nœud de fonctionnalité dans config.le fichier xml devrait ressembler à ceci:

<feature name="CustomPluginInSwift">
    <param name="ios-package" value="HWPCustomPluginInSwift" />
</feature>
25
répondu tsubik 2015-04-08 16:01:17

CDVPlugin non trouvé

Lorsque vous avez créé le fichier swift 1ère fois, Xcode vous demande de générer

<your app name>-Bridging-Header.h en-tête avec contenu vide:

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

Dans cet en-tête ajouter:

#import <Cordova/CDVPlugin.h>

Après cela, nettoyez votre projet. Si vous n'avez pas cet en - tête, créez-le.


La classe CDVPlugin CustomPluginInSwift (pluginName: CustomPluginInSwift) n'existe pas

[Étape 1]

Droit, parce que Swift utilise _TtC (tapez à la classe ) préfixe et index de classe avec le modèle suivant:

_TtC8<AppName><index#><PluginName>   

Comment savoir ce qui est bon index?

[Étape 2]

Lorsque vous lancez instance de CustomPluginInSwift classe, comme:

var temp:CustomPluginInSwift = CustomPluginInSwift()

, Swift ajoutera nouveau nom de classe à l'en-tête <AppName>-Swift.h. Le problème est que cet en-tête que vous ne pouvez pas voir dans votre projet.

Comment le trouver?

  • allez dans xCode - > Window - > Organazer - > " projet Les onglets"
  • Sélectionnez votre projet
  • copier le chemin "données dérivées" (pour moi: ~/Library/Developer/Xcode/DerivedData/<AppName>-hbgwavxfqvhwxzagxhgzjvsdrkjk)
  • allez dans la console et exécutez cd ~/Library/Developer/Xcode/DerivedData/<AppName>-hbgwavxfqvhwxzagxhgzjvsdrkjk
  • exécuter après: cd Build/Intermediates/<App name>.build/Debug-iphoneos/<App name>.build/DerivedSources/

, Vous pouvez trouver le fichier nommé: <App name>-Swift.h là, avec le contenu suivant:

/* ... */

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

/* ... */

Nous avons donc un nom propre: _TtC8Wanameet14CustomPluginInSwift

[Étape 3]

Maintenant, allez à config.xml et changez de:

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

À:

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

C'est tout,

J'espère que cela fera gagner du temps,

Testé sur cordova 3.5 + xCode6.1


Exemples

Considérez que vous avez un dossier Plugins dans votre projet (généré par Cordova).

Nous créons un nouveau fichier swift MyPlugin.swift avec le contenu suivant:

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

Exemple de méthode où nous analysons la requête javascript et retournons immédiatement la réponse:

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

}

Exemple de méthode où nous retournons callabck vide et après un certain temps retour réponse:

J'ai beaucoup utilisé ce formulaire de méthode Lorsque vous essayez d'en récupérer données du côté natif par la manière asynchrone:

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


}
10
répondu Maxim Shoustin 2014-11-27 18:27:41