SwiftDDP 0.4.1

SwiftDDP 0.4.1

测试已测试
语言语言 SwiftSwift
许可 MIT
发布上次发布2016年12月
SwiftSwift 版本3.0
SPM支持 SPM

Peter Siegesmund 维护。



 
依赖关系
CryptoSwift~> 0.6.6
SwiftWebSocket~> 2.6.5
XCGLogger>= 0
 

SwiftDDP 0.4.1

SwiftDDP

基于 Swift 编写的 Meteor 服务器客户端

版本 0.4.0

许可

MIT

安装

使用 CocoaPods。将以下行添加到您的 Podfile 中

pod "SwiftDDP", "~> 0.4.0"

快速开始

设置基本配置选项

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 服务器

// 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("[email protected]", 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)

对于每个操作,如果服务器返回错误,则将在客户端执行操作,并回滚。

示例:创建基于数组的自定义集合

以下模式可用于创建由任何数据存储支持的自定义集合

在这个例子中,我们将创建一个简单的集合来存储联系人列表。我们首先会创建一个表示联系人的对象。该对象有四个属性和一个名为 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 继承允许你覆盖在服务器事件上调用时调用的三个方法:documentWasAddeddocumentWasChangeddocumentWasRemoved

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

        }

    }
}

该方法的几个关键部分是

  • (1) 将新的联系人保存到我们在 UserCollection 中创建的数组中
  • (2) 调用 client.insert 初始化服务器上的插入操作
  • (3) 如果服务器拒绝插入,则从本地存储中删除联系人

创建更新和删除方法的操作同样简单,并且遵循与 insert 相同的模式。有关此处所示模式的更广泛示例,请参阅 MeteorCollection.swift。MeteorCollection 是一个适用于简单应用程序的内存集合实现。

变更日志

0.4.0

  • 更新到 Swift 3.0

0.3.2

  • 错误修复

0.3.1

  • 修复了影响 32 位环境中的 DDP 日期的错误

0.3.0

  • 更改默认订阅行为
  • 添加了一个通过用户名登录用户的方法

版本 0.3.0 包含破坏性更改

  • 现在可以在不先退订的情况下通过更改其参数来更新订阅。这将使客户端订阅与任何与新的订阅和参数关联的文档。当你向之前已订阅的订阅传递一组新参数时,你仍然订阅与该先前订阅相关的任何文档。
  • 订阅方法返回一个id。要取消订阅与一组特定参数关联的文档,必须使用此id进行取消订阅。
  • 通过名称退订现在工作方式不同。通过名称退订时,您将退订所有具有该名称的订阅。
  • 现在不能再传递回调给unsubscribe(name:String)了。现在它将返回您已退订的订阅的ID数组。

0.2.2.1

  • 改进了应用状态的订阅处理
  • 已针对 Swift 2.2 更新依赖

0.2.1

  • 重连行为改进:重连尝试现在遵循指数退避模式
  • 客户端现在在allowSelfSignedSSL设置为true时,使用自签名SSL证书连接到服务器
  • 现在可以直接使用客户端上的logLevel属性设置loglevel。默认设置是.None

0.2.0

  • 与Meteor的Facebook、Twitter及其他登录服务的集成

贡献

欢迎拉取请求、功能请求和反馈。如果您在生产应用中使用SwiftDDP,请告诉我们。