MultipeerConnectivity
의 전송 메서드는 크게 3종류이다.
Data 객체 전달 [링크]
[func send(Data, toPeers: [MCPeerID], with: MCSessionSendDataMode) throws](<https://developer.apple.com/documentation/multipeerconnectivity/mcsession/send(_:topeers:with:)>)
data: Data
→ 전송할 데이터toPeers: [MCPeerID]
→ 데이터를 받을 피어들의 배열with mode: MCSessionDataMode
→ 데이터를 전송할 모드를 결정하는 열거형
.reliable
→ 각 메시지의 전달을 보장함. 필요에 따라 큐에 메시지를 넣고 재전송 하기도 하고, 순서를 보장하기도 함.unreliable
→ 재전송 시도가 없으며, 순서도 보장되지 않음URL을 지정 경로에 위치한 파일을 전송 [링크]
func sendResource(
at: URL,
withName: String,
toPeer: MCPeerID,
withCompletionHandler: (((any Error)?) -> Void)?
) -> Progress?
URL
형식으로 특정 피어에게 전송at resourceURL: URL
→ 전송할 리소스의 경로withName resourceName: String
→ 수신한 피어가 보게될 리소스의 이름withCompletionHandler completionHandler: (((Error?) → Void)?)
→ 전송 완료 후 호출될 클로저Progress?
→ 파일의 전송 진행 상태파일 스트림을 전송 [링크]
func startStream(withName: String, toPeer: MCPeerID) throws -> OutputStream
withName: streamName: String
→ 스트림의 이름toPeer peerID: MCPeerID
→ 스트림을 받을 피어OutputStream
→ 생성된 스트림을 반환. 반환된 스트림에 데이터를 작성하면 피어에게 전달됨<aside> 💡
WhiteboardObject
를 상속한다.TextObject
, DrawingObject
, PhotoObject
, GameObject
까지 총 4개이다.WhiteboardObject
는 모든 오브젝트의 기본이 되는 클래스로, select
, deselect
, changeScale
, changePosition
, changeAngle
등 화이트보드에 추가되는 오브젝트라면 기본적으로 갖춰야 할 5가지의 동작을 정의한다.위와 같은 엔티티 설계를 마치고 UseCase
, Repository
설계까지 마친 시점에서 문제가 발생했다.
화이트보드에 추가된 오브젝트를 Data 타입으로 변환하여 보내는 것은 가능하나, 수신하는 입장에서 해당 오브젝트가 어떤 오브젝트인지 특정할 수 없었다.
고민을 하던 중 sendResource
메서드는 파라미터로 데이터의 이름을 특정해서 보낼 수 있다는 사실을 알게되었고, 수신하는 쪽에서 sendResource
의 withName
파라미터를 통해 오브젝트가 어떤 타입인지 특정할 수 있었다.
송신 측 코드
public func send(fileURL: URL, info: DataSource.DataInformationDTO) async {
let infoJsonData = try? JSONEncoder().encode(info)
guard
let infoJsonData,
let infoJsonString = String(data: infoJsonData, encoding: .utf8)
else { return }
await withTaskGroup(of: Void.self) { taskGroup in
session.connectedPeers.forEach { peer in
taskGroup.addTask {
do {
try await self.session.sendResource(
at: fileURL,
withName: infoJsonString,
toPeer: peer)
} catch {
self.logger.log(level: .error, "\\(peer)에게 file 데이터 전송 실패")
}
}
}
}
}
infoJsonData
를 통해 보내는 데이터의 타입을 명시한다수신 측 코드
public func session(
_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL?,
withError error: (any Error)?
) {
guard
let localURL,
let jsonData = resourceName.data(using: .utf8),
let dto = try? JSONDecoder().decode(DataInformationDTO.self, from: jsonData)
else { return }
reciptURLSubject.send((url: localURL, dataInfo: dto))
}
resourceName
을 활용해 전달받은 데이터의 타입을 특정할 수 있다session(_:didStartReceivingResourceWithName:fromPeer:with:)
메서드 호출session(_:didFinishReceivingResourceWithName:fromPeer:at:withError:)
메서드 호출