MIT
使用 CocoaPods。将以下行添加到您的 Podfile
pod "SwiftDDP", "~> 0.4.1"
使用 Swift Package Manager。将以下行添加到您的 Package.swift 中的 dependencies
.package(url: "https://github.com/y-ich/SwiftDDP.git", .branch("master")),
import SwiftDDP
Meteor.client.allowSelfSignedSSL = true // Connect to a server that uses a self signed ssl certificate
Meteor.client.logLevel = .Info // Options are: .Verbose, .Debug, .Info, .Warning, .Error, .Severe, .None
// Meteor.connect will automatically connect and will sign in using
// a stored login token if the client was previously signed in.
Meteor.connect("wss://todos.meteor.com/websocket") {
// do something after the client connects
}
使用电子邮件和密码登录。
Meteor.loginWithPassword("user@swiftddp.com", password: "********") { result, error in
// do something after login
}
使用用户名和密码登录。
Meteor.loginWithUsername("swiftddp", password: "********") { result, error in
// do something after login
}
注销。
Meteor.logout() { result, error in
// do something after logout
}
当用户登录和注销以及连接失败事件期间,客户端还会发布通知。
// Notification name (a string global variable)
DDP_USER_DID_LOGIN
DDP_USER_DID_LOGOUT
//Websocket/DDP connection failure events
DDP_WEBSOCKET_CLOSE
DDP_WEBSOCKET_ERROR
DDP_DISCONNECTED
DDP_FAILED
// Example
NSNotificationCenter.defaultCenter().addObserver(self, selector: "userDidLogin", name: DDP_USER_DID_LOGIN, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "userDidLogout", name: DDP_USER_DID_LOGOUT, object: nil)
func userDidLogin() {
print("The user just signed in!")
}
func userDidLogout() {
print("The user just signed out!")
}
Meteor.subscribe("todos")
Meteor.subscribe("todos") {
// Do something when the todos subscription is ready
}
Meteor.subscribe("todos", [1,2,3,4]) {
// Do something when the todos subscription is ready
}
// Suppose you want to subscribe to a list of all cities and towns near a specific major city
// Subscribe to cities near Boston
let id1 = Meteor.subscribe("cities", ["lat": 42.358056 ,"lon": -71.063611]) {
// You are now subscribed to cities associated with the coordinates 42.358056, -71.063611
// id1 contains a key that allows you to cancel the subscription associated with
// the parameters ["lat": 42.358056 ,"lon": -71.063611]
}
// Subscribe to cities near Paris
let id2 = Meteor.subscribe("cities", ["lat": 48.8567, "lon": 2.3508]){
// You are now subscribed to cities associated with the coordinates 48.8567, 2.3508
// id2 contains a key that allows you to cancel the subscription associated with
// the parameters ["lat": 48.8567 ,"lon": 2.3508]
}
// Subscribe to cities near New York
let id3 = Meteor.subscribe("cities", ["lat": 40.7127, "lon": -74.0059]){
// You are now subscribed to cities associated with the coordinates 40.7127, -74.0059
// id3 contains a key that allows you to cancel the subscription associated with
// the parameters ["lat": 40.7127 ,"lon": -74.0059]
}
// When these subscriptions have completed, the collection associated with "cities" will now contain all
// documents returned from the three subscriptions
Meteor.unsubscribe(withId: id2)
// Your collection will now contain cities near Boston and New York, but not Paris
Meteor.unsubscribe("cities")
// You are now unsubscribed to all subscriptions associated with the publication "cities"
Meteor.call("foo", [1, 2, 3, 4]) { result, error in
// Do something with the method result
}
当向服务器方法传递参数时,参数对象必须可使用 NSJSONSerialization 序列化
SwiftDDP 包含一个名为 MeteorCollection 的类,它提供简单的、临时的字典支持的持久化。MeteorCollection 存储从 MeteorDocument 子类化的对象。创建一个集合非常简单,只需
class List: MeteorDocument {
var collection:String = "lists"
var name:String?
var userId:String?
}
let lists = MeteorCollection<List>(name: "lists") // As with Meteorjs, the name is the name of the server-side collection
Meteor.subscribe("lists")
对于客户端的插入、更新和删除
let list = List(id: Meteor.client.getId(), fields: ["name": "foo"])
// Insert the object on both the client and server.
lists.insert(list)
// Update the object on both the client and server
list.name = "bar"
lists.update(list)
// Remove the object on both the client and server
lists.remove(list)
对于每个操作,操作都在客户端执行,如果服务器返回错误,则回滚。
如果您制作命令行工具,您需要在适当的 DDP 设置后在主线程中调用函数 dispatchMain。否则,您将遇到死锁。
Meteor.connect("wss://todos.meteor.com/websocket") {
// do something after the client connects
}
dispatchMain()
以下模式可用于创建由任何数据存储支持的自定义集合
在本示例中,我们将创建一个简单的集合来保存联系人列表。我们要做的第一件事是创建一个对象来表示联系人。此对象具有四个属性和一个名为 update 的方法,该方法将 fields NSDictionary 映射到结构体的属性。当创建对象和执行更新时,将调用Update。Meteor 将始终传输一个 id 来标识应该添加、更新或删除的对象,因此表示 Meteor 文档的对象必须始终具有 id 字段。在这里,我们坚持 MongoDB 的命名约定,将我们的 id 命名为 _id。
struct Contact {
var _id:String?
var name:String?
var phone:String?
var email:String?
init(id:String, fields:NSDictionary?) {
self._id = id
update(fields)
}
mutating func update(fields:NSDictionary?) {
if let name = fields?.valueForKey("name") as? String {
self.name = name
}
if let phone = fields?.valueForKey("phone") as? String {
self.phone = phone
}
if let email = fields?.valueForKey("email") as? String {
self.email = email
}
}
}
接下来,我们将创建集合类,该类将保存我们的联系人并提供逻辑来响应服务器端对文档和订阅集的更改。SwiftDDP 包含一个名为 AbstractCollection 的抽象类,可用于构建自定义集合。子类化 AbstractCollection 允许您覆盖在响应服务器上的事件时调用的三个方法:documentWasAdded、documentWasChanged 和 documentWasRemoved。
class UserCollection: AbstractCollection {
var contacts = [Contact]()
// Include any logic that needs to occur when a document is added to the collection on the server
override public func documentWasAdded(collection:String, id:String, fields:NSDictionary?) {
let user = User(id, fields)
users.append(user)
}
// Include any logic that needs to occur when a document is changed on the server
override public func documentWasChanged(collection:String, id:String, fields:NSDictionary?, cleared:[String]?) {
if let index = contacts.indexOf({ contact in return contact._id == id }) {
contact = contacts[index]
contact.update(fields)
contacts[index] = contact
}
}
// Include any logic that needs to occur when a document is removed on the server
override public func documentWasRemoved(collection:String, id:String) {
if let index = contacts.indexOf({ contact in return contact._id == id }) {
contacts[index] = nil
}
}
}
到目前为止,我们能够处理在服务器上添加、更改或删除的文档。但是 UserCollection 类仍然缺乏更改本地数据存储和服务器的能力。我们将改变这一点。在 UserCollection 类中,创建一个名为 insert 的方法。
class UserCollection: AbstractCollection {
/*
override public func documentWasAdded ...
override public func documentWasChanged ...
override public func documentWasRemoved ...
*/
public func insert(contact: Contact) {
// (1) save the document to the contacts array
contacts[contacts._id] = contact
// (2) now try to insert the document on the server
client.insert(self.name, document: [contacts.fields()]) { result, error in
// (3) However, if the server returns an error, reverse the action on the client by
// removing the document from the contacts collection
if error != nil {
self.contacts[contact._id] = nil
log.error("\(error!)")
}
}
}
}
此方法的关键部分是
创建 update 和 remove 方法也很容易,并且遵循与 insert 相同的模式。有关此处显示的模式的更广泛示例,请查看 MeteorCollection.swift。MeteorCollection 是一个适用于简单应用程序的内存集合实现。
版本 0.3.0 包含重大更改
unsubscribe(name:String)
。它现在返回一个包含您已取消订阅的订阅 id 的数组。欢迎提交拉取请求、功能请求和反馈。如果您在生产应用程序中使用 SwiftDDP,请告诉我们。