NKMultipeer 1.0.4

NKMultipeer 1.0.4

测试已测试
Lang语言 SwiftSwift
许可证 MIT
Released上次发布2016 年 4 月
SPM支持 SPM

Nathan Kot 维护。



 
依赖
RxSwift~> 2.3.0
RxCocoa~> 2.3.0
 

  • Nathan Kot

围绕 MultipeerConnectivity 的可测试、Rx* 包装器

使用适配器模式,我们可以使用大量的模拟来测试多点连接代码。实际上,我们试图将 MultipeerConnectivity 中的所有不可测试的部分集中到一个库中。

此库还允许您用其他协议(如 WebSocket)替换底层的 p2p 机制。目前它只支持苹果的 MultipeerConnectivity,但你可以轻松编写对其他协议的自定义适配器。

请注意,NKMultipeer 了大量使用 RxSwift,如果您不熟悉 Rx* 库,请阅读相关内容。此库的箴言是:**一切皆流**。

安装

示例代码

要查看有效示例,请查看 NKMultipeer 示例 文件夹。

广播并提供附近的对等的节点

import RxSwift
import RxCocoa
import NKMultipeer

let acceptButton: UIButton
let client: CurrentClient<MCPeerID>

client.startAdvertising()
let connectionRequests = client.incomingConnections().shareReplay(1)

acceptButton.rx_tap
  .withLatestFrom(connectionRequests)
  .subscribeNext { (peer, context, respond) in respond(true) }
  .addDisposableTo(disposeBag)

寻找和连接到他的人格

import RxSwift
import NKMultipeer

let client: CurrentClient<MCPeerID>

client.startBrowsing()

let nearbyPeers = client.nearbyPeers().shareReplay(1)

// Attempt to connect to all peers
nearbyPeers
  .map { (peers: [Client<MCPeerID>]) in
    peers.map { client.connect($0, context: ["Hello": "there"], timeout: 12) }.zip()
  }
  .subscribe()
  .addDisposableTo(disposeBag)

发送和接收字符串

发送它们

import RxSwift
import RxCocoa
import NKMultipeer

let client: CurrentClient<MCPeerID>
let peer: Observable<Client<MCPeerID>>
let sendButton: UIButton

sendButton.rx_tap
  .withLatestFrom(peer)
  .map { client.send(peer, "Hello!") }
  .switchLatest()
  .subscribeNext { _ in print("Message sent") }
  .addDisposableTo(disposeBag)

接收它们

import RxSwift
import NKMultipeer

let client: CurrentClient<MCPeerID>

client.receive()
.subscribeNext { (peer: Client<MCPeerID>, message: String) in
  print("got message \(message), from peer \(peer)")
}
.addDisposableTo(disposeBag)

建立数据流

RxSwift 使得向另一个节点持久连接发送流数据变得非常直观。

发送者

import RxSwift
import NKMultipeer

let client: CurrentClient<MCPeerID>
let peer: Observable<Client<MCPeerID>>
let queuedMessages: Observable<[UInt8]>

let pipe = peer.map { client.send(peer, streamName: "data.stream") }
pipe.withLatestFrom(queuedMessages) { $0 }
  .subscribeNext { (sender, message) in sender(message) }
  .addDisposableTo(disposeBag)

接收者

import RxSwift
import NKMultipeer

let client: CurrentClient<MCPeerID>
let peer: Observable<Client<MCPeerID>>

let incomingData = client.receive(peer, streamName: "data.stream").shareReplay(1)
incomingData.subscribeNext { (data) in print(data) }
  .addDisposableTo(disposeBag)

使用方法

导入

import RxSwift
import NKMultipeer

为测试创建新的构建配置

您的项目默认带有 DebugRelease 构建配置,我们需要创建一个新的名为 Testing 的配置。请在此处查看逐步说明

设置客户端

// See the link above,
// You'll need to define a new build configuration and give it the `TESTING` flag
let name = UIDevice.currentDevice().name
#if TESTING
typealias I = MockIden
let client = CurrentClient(session: MockSession(name: name))
#else
typealias I = MCPeerID
let client = CurrentClient(session: MultipeerConnectivitySession(
                 displayName: name,
                 serviceType: "multipeerex",
                 encryptionPreference: .None))
#endif

支持的传输资源类型

字符串

func send(other: Client, _ string: String, _ mode: MCSessionSendDataMode = .Reliable) -> Observable<()>
func receive() -> Observable<(Client, String)>

NSData

func send(other: Client, _ data: NSData, _ mode: MCSessionSendDataMode = .Reliable) -> Observable<()>
func receive() -> Observable<(Client, NSData)>

JSON

func send(other: Client, _ json: [String: AnyObject], _ mode: MCSessionSendDataMode = .Reliable) -> Observable<()>
func receive() -> Observable<(Client, [String: AnyObject])>

NSURL

func send(other: Client, name: String, url: NSURL, _ mode: MCSessionSendDataMode = .Reliable) -> Observable<NSProgress>
func receive() -> Observable<(Client, String, ResourceState)>

NSStream

func send(other: Client, streamName: String, runLoop: NSRunLoop = NSRunLoop.mainRunLoop()) -> Observable<([UInt8]) -> Void>
func receive(other: Client, streamName: String, runLoop: NSRunLoop = NSRunLoop.mainRunLoop(), maxLength: Int = 512) -> Observable<[UInt8]>

测试

在测试时,使用预处理器宏确保您的代码使用 MockSession 实例而不是 MultipeerConnectivitySession 实例。为了实现这一点,您需要使用预处理器标志并替换引用 Client<T> 的任何地方(因为 T 会有所不同,具体取决于您是否在测试。) 首先,您需要 设置一个新的构建配置,然后您可以使用如下预处理器宏。

let name = UIDevice.currentDevice().name
#if TESTING
typealias I = MockIden
let client = CurrentClient(session: MockSession(name: name))
#else
typealias I = MCPeerID
let client = CurrentClient(session: MultipeerConnectivitySession(
                 displayName: name,
                 serviceType: "multipeerex",
                 encryptionPreference: .None))
#endif

别担心,您实际上通常只需要在一个集中位置使用预处理器宏,编译器之后可以根据客户端的类型进行推断。

在测试环境中模拟其他附近的设备变得非常简单,只需创建其他 CurrentClient(session: MockSession(name: "other"))。例如,如果您的应用程序在测试环境中运行,下面的代码将模拟一个附近的客户端

let otherclient = CurrentClient(session: MockSession(name: "mockedother"))

// Accept all connections
otherclient.startAdvertising()
otherclient.incomingConnections()
.subscribeNext { (client, context, respond) in respond(true) }
.addDisposableTo(disposeBag)

// Respond to all messages with 'Roger'
otherclient.receive()
.map { (client: Client<MockIden>, string: String) in return otherclient.send(client, "Roger") }
.concat()
.subscribeNext { _ in print("Response sent") }
.addDisposableTo(disposeBag)

贡献

  • 缩进使用两个空格
  • 删除尾随空白字符
  • 编写测试
  • 从功能分支发起拉取请求。