用户网格SDK 2.1.3

用户网格SDK 2.1.3

测试已测试
语言语言 SwiftSwift
许可 Apache 2
发布最后发布2017年2月
SwiftSwift 版本3.0
SPM支持 SPM

Robert WalshRobert Walsh 维护。



用户网格Swift SDK

用Swift编写的用户网格SDK

要求

虽然用户网格SDK是用Swift编写的,但其功能与Objective-C保持兼容。

在您的Objective-C文件中使用 #import <UsergridSDK/UsergridSDK-Swift.h> 来启用SDK的功能。

  • iOS 8.0+ / Mac OS X 10.11+ / tvOS 9.1+ / watchOS 2.1+
  • Xcode 8.0+
  • Swift 3.0+

安装

嵌入式框架

嵌入式框架至少需要iOS 8或OS X Mavericks(10.9)的部署目标。

  • 打开终端,使用 cd 进入您的顶级项目目录,然后运行以下命令,如果您的项目未初始化为git仓库:
$ git init
  • 通过运行以下命令将用户网格SDK添加为git子模块:
$ git submodule add https://github.com/apache/usergrid
  • UsergridSDK.xcodeproj 拖入您的应用程序Xcode项目的“项目导航器”。

它应该出现在您的应用程序蓝色项目图标之下。

  • 在项目导航器中选择 UsergridSDK.xcodeproj,并验证部署目标与您的应用程序目标相匹配。
  • 接下来,在项目导航器中选择您的应用程序项目(蓝色项目图标)以导航到目标配置窗口,并在侧边栏的“目标”标题下选择应用程序目标。
  • 在窗口顶部的标签栏中,打开“通用”面板。
  • 在“嵌入式二进制文件”部分下点击 + 按钮。
  • 选择 UsergridSDK.framework

UsergridSDK.framework 将自动添加为目标依赖项、链接框架和复制文件构建阶段的嵌入式框架,这些正是您在模拟器和设备上构建所需要的东西。

文档

此库的文档在此处可用:这里

初始化

有两种不同的方式可以初始化用户网格Swift SDK

  1. 单例模式既方便又允许开发者使用全局可用且始终初始化的用户网格实例。
Usergrid.initSharedInstance(orgId: "orgId", appId: "appId")
  1. 实例模式允许开发者以独立和隔离的方式管理Usergrid客户端的实例。主要用例是当应用程序连接到多个Usergrid目标时。
let client = UsergridClient(orgId: "orgId", appId: "appId")

注意:本readme中的示例假设您正在使用共享实例的Usergrid。如果您实现了实例模式,只需将Usergrid替换为您的客户端实例变量即可。

推送通知

注意:您必须有苹果开发者账号以及已设置的有效的配置文件,才能接收推送通知。

为了使用Usergrid推送通知,您必须使用Usergrid推送通知标识符注册设备。

有关接收推送通知和发送推送通知(从设备)的更详细示例,请参阅位于/Samples文件夹中的推送示例应用程序。

以下代码片段显示了如何在应用程序代理中注册推送通知并将推送令牌应用在其中。

import UsergridSDK

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        // Initialize the shared instance of Usergrid.
        Usergrid.initSharedInstance(orgId:"orgId", appId: "appId")

        // Register for APN
        application.registerUserNotificationSettings(UIUserNotificationSettings( forTypes: [.Alert, .Badge, .Sound], categories: nil))
        application.registerForRemoteNotifications()

        return true
    }

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        Usergrid.applyPushToken(deviceToken, notifierID: "notifierId") { response in
            // The push notification is now added to Usergrid for this device and this device will now be able to recieve notifications.
        }
    }
}

RESTful操作

在发起任何RESTful调用时,始终需要一个type参数(或path)。您是将其指定为参数还是作为对象的参数,由您决定。

GET

  • 获取集合中的实体
Usergrid.GET("collection") { response in
    var entities: [UsergridEntity]? = response.entities
}
  • 通过uuid或名称在集合中获取特定实体
Usergrid.GET("collection", uuidOrName:"<uuid-or-name>") { response in
    var entity: UsergridEntity? = response.entity?
}
  • 通过传递UsergridQuery对象在集合中获取特定实体
var query = UsergridQuery("cats").gt("weight", value: 2.4)
                                 .contains("color", value:"bl*")
                                 .not()
                                 .eq("color", value:"blue")
                                 .or()
                                 .eq("color", value:"orange")

// this will build out the following query:
// select * where weight > 2.4 and color contains 'bl*' and not color = 'blue' or color = 'orange'

Usergrid.GET(query) { response in
    var entities: [UsergridEntity]? = response.entities
}

POST和PUT

POST和PUT请求都需要JSON体负载。您可以传递Swift对象或UsergridEntity实例。虽然前一种在原则上可行,但最佳实践是在适用的情况下使用UsergridEntity。当实体具有uuid或名称属性并且已在服务器上存在时,使用PUT请求更新它。如果它不存在,则使用POST来创建它。

  • 在集合中创建新的实体(POST
var entity = UsergridEntity(type: "restaurant", propertyDict: ["restaurant": "Dino's Deep Dish","cuisine": "pizza"])

Usergrid.POST(entity) { response in
    // entity should now have a uuid property and be created
}

// you can also POST an array of entities:

var entities = [UsergridEntity(type: "restaurant", propertyDict:["restaurant": "Dino's Deep Dish","cuisine": "pizza"]), 
                UsergridEntity(type: "restaurant", propertyDict:["restaurant": "Pizza da Napoli","cuisine": "pizza"])]

Usergrid.POST(entities) { response in
    // response.entities should now contain now valid posted entities.
}
  • 在集合中更新实体(PUT
var entity = UsergridEntity(type: "restaurant", propertyDict:["restaurant": "Dino's Deep Dish", "cuisine": "pizza"])

Usergrid.POST(entity) { response in
    if let responseEntity = response.entity {
        responseEntity["owner"] = "Mia Carrara"
        Usergrid.PUT(responseEntity) { (response) -> Void in
            // entity now has the property 'owner'
        }
    }
}

// or update a set of entities by passing a UsergridQuery object

var query = UsergridQuery("restaurants").eq("cuisine", value:"italian")

Usergrid.PUT(query, jsonBody: ["keywords":["pasta"]]) { response in

    /* the first 10 entities matching this query criteria will be updated:
    e.g.:
        [
            {
                "type": "restaurant",
                "restaurant": "Il Tarazzo",
                "cuisine": "italian",
                "keywords": ["pasta"]
            },
            {
                "type": "restaurant",
                "restaurant": "Cono Sur Pizza & Pasta",
                "cuisine": "italian",
                "keywords": ["pasta"]
            }
        ]
    */
}

DELETE

DELETE请求需要传递特定实体或作为参数传递的UsergridQuery对象。

  • 通过uuid或名称在集合中删除特定实体
Usergrid.DELETE("collection", uuidOrName: "<uuid-or-name>") { response in
    // if successful, entity will now be deleted
})
  • 通过传递UsergridQuery对象来删除集合中的特定实体
let query = UsergridQuery("cats").eq("color", value:"black")
                                 .or()
                                 .eq("color", value:"white")

// this will build out the following query:
// select * where color = 'black' or color = 'white'

Usergrid.DELETE(query) { response in
    // the first 10 entities matching this query criteria will be deleted
}

实体操作和便捷方法

UsergridEntity提供了一些帮助/便捷方法,使与实体的交互更加方便。

reload()

从服务器重新加载实体

entity.reload() { response in
    // entity is now reloaded from the server
}

save()

在服务器上保存(或创建)实体

entity["aNewProperty"] = "A new value"
entity.save() { response in
    // entity is now updated on the server
}

remove()

从服务器删除实体

entity.remove() { response in
    // entity is now deleted on the server and the local instance should be destroyed
}

身份验证、当前用户和authMode

appAuth和authenticateApp()

Usergrid可以使用初始化时传递的app客户端ID和密钥,自动检索用于这些凭据的应用程序级别令牌。

Usergrid.setAppAuth("<client-id>", "<client-secret>")
Usergrid.authenticateApp() { response in
    // Usergrid.appAuth is authenticated automatically when this call is successful
}

当前用户,用户身份验证和authenticateUser()

Usergrid具有一个特殊的currentUser属性。

当前用户信息存储在钥匙串中,以便于在应用重新启动后保持用户的登录和令牌信息。要调整此功能,请在初始化时编辑Usergrid.persistCurrentUserInKeychain属性。

默认情况下,在调用authenticateUser()时,如果身份验证流程成功,将.currentUser设置为该用户。

let userAuth = UsergridUserAuth(username: "<username>", password: "<password>")
Usergrid.authenticateUser(userAuth) { auth, user, error in
    // Usergrid.currentUser is set to the authenticated user and the token is stored within that context
}

如果您想在未将其设置为当前用户的情况下使用authenticateUser,只需将布尔值作为第二个参数传递为false

let userAuth = UsergridUserAuth(username: "<username>", password: "<password>")
Usergrid.authenticateUser(userAuth,setAsCurrentUser: false) { auth, user, error in
    // user is authenticated but Usergrid.currentUser is not set.
}

认证模式

认证模式用于确定UsergridClient将用于授权的内容。

默认情况下,Usergrid.authMode被设置为.User,在这种情况下,如果UsergridClient.currentUser中存在非过期的UsergridUserAuth,将使用这个令牌对所有API调用进行认证。

如果将Usergrid.authMode设置为.None,则所有API调用都将未认证执行。

如果将Usergrid.authMode设置为.App,则所有API调用都将使用客户端凭证令牌执行,如果有可用的令牌(即在某处执行了authenticateApp())。

使用认证上下文

有时候,可能希望对API调用的认证上下文有完整的、粒度化的控制。

为此,passthrough函数.usingAuth()允许您预先定义下一个API调用的认证上下文。

// assume Usergrid.authMode = .None

Usergrid.usingAuth(Usergrid.appAuth!).POST("roles/guest/permissions", jsonBody: ["permission" : "get,post,put,delete:/**"] ) { response in
    // here we've temporarily used the client credentials to modify permissions
    // subsequent calls will not use this auth context
}

用户操作和便捷方法

UsergridUser具有一些助手/便捷方法,以便更方便地处理用户实体。如果您没有使用Usergrid共享实例,您必须将这些助手方法作为第一个参数传递一个UsergridClient实例。

create()

创建新用户

let user = UsergridUser(username: "username", password: "password")
user.create() { response in
    // user has now been created and should have a valid uuid
}

login()

以更简单的方式获取用户级别的令牌

user.login("username", password: "password") { auth, user, error in
    // user is now logged in
}

logout()

注销所选用户。您也可以在Usergrid.currentUser上使用此便捷方法。

user.logout() { response in
    // user is now logged out
}

resetPassword()

重置所选用户的密码。

user.resetPassword("oldPassword", new: "newPassword") { error, didSucceed in
    // if it was done correctly, the new password will be changed
    // 'didSucceed' is a boolean value that indicates whether it was changed successfully
}

UsergridUser.CheckAvailable()

这是一个类(静态)方法,允许您检查用户名或电子邮箱地址是否可用。

UsergridUser.checkAvailable("email", username: nil) { error, available in
    // 'available' == whether an email already exists for a user
}

UsergridUser.checkAvailable(nil, username: "username") { error, available in
    // 'available' == whether an username already exists for a user
}

UsergridUser.checkAvailable("email", username: "username") { error, available in
    // 'available' == whether an email or username already exist for a user
}

查询和过滤数据

UsergridQuery初始化

UsergridQuery类允许您使用Usergrid查询语法构建复杂的查询过滤器。

UsergridQuery构建模式的第一个参数应该是您打算查询的集合(或类型)。您可以将其传递作为一个参数,或者作为第一个构建对象。

var query = UsergridQuery("cats")
// or
var query = UsergridQuery().collection("cats")

然后可以添加额外的查询。

var query = UsergridQuery("cats").gt("weight", value: 2.4)
                                 .contains("color", value: "bl*")
                                 .not()
                                 .eq("color", value:"white")
                                 .or()
                                 .eq("color", value:"orange")

您还可以调整返回结果的数量

var query = UsergridQuery("cats").eq("color", value: "black")
                                 .limit(100)

// returns a maximum of 100 entiteis

并且可以排序结果

var query = UsergridQuery("cats").eq("color", value: "black")
                                 .limit(100)
                                 .asc("name")

// sorts by 'name', ascending

并且可以进行地理定位查询

var query = UsergridQuery("devices").locationWithin(<distance>, latitude: <lat>, longitude: <long>)

在请求中使用查询

可以将查询作为参数传递给GET、PUT和DELETE请求

Usergrid.GET("type", query: query) { response in
    // Gets entities of a given type matching the query.
}

Usergrid.PUT(query, jsonBody: ["aNewProperty":"A new value"]) { response in
    // Updates the entities matching the query with the new property.
}

Usergrid.DELETE(query) { response in
    // Deletes entities of a given type matching the query.
}

查询构建器对象列表

type("string")

查询的集合名称

collection("string")

type的别名

eq("key", value: "value")equals("key", value: "value")filter("key", value: "value")

等于(例如:where color = 'black'

contains("key", value: "value")containsString("key", value: "value")containsWord("key", value: "value")

包含字符串(例如:where color contains 'bl*'

gt("key", value: "value")greaterThan("key", value: "value")

大于(例如:where weight > 2.4

gte("key", value: "value")greaterThanOrEqual("key", value: "value")

大于等于(例如:where weight >= 2.4

lt("key", value: "value")lessThan("key", value: "value")

小于(例如:where weight < 2.4

lte("key", value: "value")lessThanOrEqual("key", value: "value")

小于等于(例如:where weight <= 2.4

not()

否定构建器模式中的下一条语句,例如:

var query = UsergridQuery("cats").not().eq("color", value: "black")
// select * from cats where not color = 'black'

and()

通过要求两个查询都满足来连接两个查询。and在连接两个查询时不带操作符时也是隐含的。例如:

var query = UsergridQuery("cats").eq("color", value:"black").eq("fur", value:"longHair")
// is identical to:
var query = UsergridQuery("cats").eq("color", value:"black").and().eq("fur", value:"longHair")  

or()

通过只要求满足其中一个查询来连接两个查询。or永远不会隐含。例如:

var query = UsergridQuery("cats").eq("color",value: "black").or().eq("color", value: "white")

当使用or()and()运算符时,and()连接的优先级高于or()连接。您可以在此处阅读有关查询运算符和优先级的更多信息:

locationWithin(distanceInMeters, latitude: latitude, longitude: longitude)

返回在指定半径内的实体。参数可以是floatint

asc("key")ascending("key")

按指定属性升序排序结果

desc("key")descending("key")

按指定属性降序排序结果

sort("key", value: .Asc)

按指定属性,在指定的UsergridQuerySortOrder.Asc.Desc)中排序结果

limit(int)

要返回的最大实体数

cursor("string")

分页游标字符串

fromString("query string")

一个特殊的构建器属性,允许您输入预定义的查询字符串。当定义此属性时,将忽略所有构建器属性。例如

var query = UsergridQuery().fromString("select * where color = 'black' order by name asc")

UsergridResponse对象

UsergridResponse是处理Usergrid成功和失败HTTP响应的核心类。

如果请求成功,响应中返回的任何实体都将自动解析为UsergridEntity对象,并推送到entities属性。

如果请求失败,error属性将包含关于遇到的问题的信息。

ok

您可以通过检查UsergridResponse.ok,一个Bool值,来查看响应是否成功。任何状态码< 400返回true。

Usergrid.GET("collection") { response in
    if response.ok {
        // woo!
    }
}

entity,entities,user,users,first,last

根据您进行的调用,响应中返回的任何实体都将自动解析为UsergridEntity对象,并推送到entities属性。如果您正在查询users集合,这些也将是UsergridUser对象,它是UsergridEntity的子类。

  • .first返回实体数组中的第一个实体;.entity.first的别名。如果没有实体,这两个都将是未定义的。

  • .last返回实体数组中的最后一个实体;如果数组中只有一个实体,这将与.first.entity相同,如果没有实体,将为未定义。

  • .entities将是响应中的实体数组,或者是一个空数组。

  • .user是一种特殊别名,用于查询users集合时的.entity。它不是UsergridEntity对象,而是它的子类UsergridUser

  • .users.user相同,不过其行为类似于.entities,返回一个包含UsergridUser对象数组的数组,或者一个空数组。

示例

Usergrid.GET("collection") { response in
    // you can access:
    //     response.entities (the returned entities)
    //     response.first (the first entity)
    //     response.entity (same as response.first)
    //     response.last (the last entity returned)
}

Usergrid.GET("collection", uuidOrName:"<uuid-or-name>") { response in
    // you can access:
    //     response.entity (the returned entity) 
    //     response.entities (containing only the returned entity)
    //     response.first (same as response.entity)
    //     response.last (same as response.entity)
}

Usergrid.GET("users") { response in
    // you can access:
    //     response.users (the returned users)
    //     response.entities (same as response.users)
    //     response.user (the first user)    
    //     response.entity (same as response.user)   
    //     response.first (same as response.user)  
    //     response.last (the last user)
}

Usergrid.GET("users", uuidOrName:"<uuid-or-name>") { response in
    // you can access;
    //     response.users (containing only the one user)
    //     response.entities (same as response.users)
    //     response.user (the returned user)    
    //     response.entity (same as response.user)   
    //     response.first (same as response.user)  
    //     response.last (same as response.user)  
}

连接

可以使用Usergrid.connect()Usergrid.disconnect()Usergrid.getConnections()或同名的实体便捷方法来管理连接。

当通过Usergrid.getConnections()检索连接时,您可以通过传入一个可选的UsergridQuery对象来过滤返回的已连接实体。

连接

在两个实体之间创建连接

Usergrid.connect(entity1, relationship: "relationship", to: entity2) { response in
    // entity1 now has an outbound connection to entity2
}

检索连接

检索出站连接

Usergrid.getConnections(.Out, entity: entity1, relationship: "relationship", query: nil) { response in
    // entities is an array of entities that entity1 is connected to via 'relationship'
    // in this case, we'll see entity2 in the array
}

检索入站连接

Usergrid.getConnections(.In, entity: entity2, relationship: "relationship", query: nil) { response in
    // entities is an array of entities that connect to entity2 via 'relationship'
    // in this case, we'll see entity1 in the array
}

断开连接

删除两个实体之间的连接

Usergrid.disconnect(entity1, relationship: "relationship", from: entity2) { response in
    // entity1's outbound connection to entity2 has been destroyed
}

资源

可以使用Usergrid.uploadAsset()Usergrid.downloadAsset()直接上传和下载资源,或者使用具有相同名称的同名UsergridEntity便捷方法。在上传资源之前,您需要初始化一个UsergridAsset实例。

初始化

注意:初始化UsergridAsset对象时指定文件名是可选的。

  • 使用NSData
let image = UIImage(contentsOfFile: "path/to/image")
let data = UIImagePNGRepresentation(image)
let asset = UsergridAsset(fileName:"<file-name-or-nil>", data: data!, contentType:"image/png")
  • 使用UIImage对象
let image = UIImage(contentsOfFile: "path/to/image")
let asset = UsergridAsset(fileName:"<file-name-or-nil>", image: image!, imageContentType: .Png)
  • 使用文件URL
let fileUrl = NSURL(string: "local/path/to/file")
if fileUrl.isFileReferenceURL() {  // This must be a file reference url.
    let asset = UsergridAsset(fileName:"<file-name-or-nil>", fileUrl: fileUrl!, contentType:"<content-type>")
}

上传

上传一个图片并连接到实体

let image = UIImage(contentsOfFile: "path/to/image")
let asset = UsergridAsset(fileName:"<file-name-or-nil>", image: image!, imageContentType: .Png)!
Usergrid.uploadAsset(entity,
                     asset: asset,
                     progress: { bytesFinished, bytesExpected in
                        // Monitor the upload progress
                     },
                     completion: { asset, response in
                        // The asset is now uploaded to Usergrid and entity.asset == asset
})

下载

下载与实体连接的图片

Usergrid.downloadAsset(entity,
                       contentType: "<expected-content-type>",
                       progress: { bytesFinished, bytesExpected in
                            // Monitor the download progress
                       },
                       completion:{ asset, error in
                            // The asset is now downloaded from Usergrid and entity.asset == asset
})

自定义UsergridEntity子类

创建基础UsergridEntity类(类似于UsergridUserUsergridDevice)的自定义子类是可能的。

有关创建自定义子类的示例,请参阅位于/Samples文件夹中的ActivityFeed示例应用。那里的自定义子类名为ActivityEntity

  • 为此,可以创建UsergridEntity的子类并实现所需的方法
import UsergridSDK

public class ActivityEntity: UsergridEntity {

    required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
        super.init(type: type, name: name, propertyDict: propertyDict)
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}
  • 您还需要注册自定义子类
Usergrid.initSharedInstance(orgId: "orgId", appId: "appId")
UsergridEntity.mapCustomType("activity", toSubclass: ActivityEntity.self)

通过注册自定义子类,UsergridEntityUsergridResponse 类能够根据实体的 type 生成这些类的实例。

在上面的示例中,具有 type 值为 activity 的实体现在可以被转换为 ActivityEntity 对象。例如:

Usergrid.GET("activity") { response in
    var activityEntities: [ActivityEntity]? = response.entities as? [ActivityEntity]
}