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