-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathViewController.swift
189 lines (148 loc) · 7.84 KB
/
ViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//
// ViewController.swift
// SelfieShare
//
// Created by Julian Moorhouse on 18/08/2019.
// Copyright © 2019 Mindwarp Consultancy Ltd. All rights reserved.
//
import MultipeerConnectivity
import UIKit
class ViewController: UICollectionViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate {
var images = [UIImage]()
var peerID = MCPeerID(displayName: UIDevice.current.name)
var mcSession: MCSession?
var mcAdvertiserAssistant: MCAdvertiserAssistant?
var connectedPeers = [String]()
override func viewDidLoad() {
super.viewDidLoad()
title = "Selfie Share"
let connect = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(showConnectionPrompt))
let peers = UIBarButtonItem(barButtonSystemItem: .organize, target: self, action: #selector(showPeers))
navigationItem.leftBarButtonItems = [connect, peers]
let camera = UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(importPicture))
let sendText = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(sendMessage))
navigationItem.rightBarButtonItems = [camera, sendText]
mcSession = MCSession(peer: peerID, securityIdentity: nil, encryptionPreference: .required)
mcSession?.delegate = self
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageView", for: indexPath)
if let imageView = cell.viewWithTag(1000) as? UIImageView {
imageView.image = images[indexPath.item]
}
return cell
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
dismiss(animated: true)
images.insert(image, at: 0)
collectionView.reloadData()
guard let mcSession = mcSession else { return }
if mcSession.connectedPeers.count > 0 {
if let imageData = image.pngData() {
do {
try mcSession.send(imageData, toPeers: mcSession.connectedPeers, with: .reliable)
} catch {
let ac = UIAlertController(title: "Send error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
}
}
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {}
func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {}
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {}
func browserViewControllerDidFinish(_ browserViewController: MCBrowserViewController) {
dismiss(animated: true)
}
func browserViewControllerWasCancelled(_ browserViewController: MCBrowserViewController) {
dismiss(animated: true)
}
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
switch state {
case .connected:
print("Connected: \(peerID.displayName)")
connectedPeers.append(peerID.displayName)
case .connecting:
print("Connecting: \(peerID.displayName)")
case .notConnected:
print("Not Connected: \(peerID.displayName)")
let ac = UIAlertController(title: "Connection Status", message: "\(peerID.displayName) has disconnected", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
@unknown default:
print("Unknown state received: \(peerID.displayName)")
}
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
DispatchQueue.main.async { [weak self] in
if let image = UIImage(data: data) {
self?.images.insert(image, at: 0)
self?.collectionView.reloadData()
} else {
guard let message = String(decoding: data, as: UTF8.self) as String? else { return }
let ac = UIAlertController(title: "New received message", message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self?.present(ac, animated: true)
}
}
}
@objc func importPicture() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
@objc func sendMessage() {
let ac = UIAlertController(title: "Text message", message: "Enter you message to send to peers", preferredStyle: .alert)
ac.addTextField()
let submitAction = UIAlertAction(title: "Submit", style: .default) {
[weak self, weak ac] _ in // specifies input into closure, ac is a weak reference
// using ac? as its a weak reference
guard let message = ac?.textFields?[0].text else { return }
self?.sendText(message: message)
}
ac.addAction(submitAction)
present(ac, animated: true)
}
@objc func showConnectionPrompt() {
let ac = UIAlertController(title: "Connect to others", message: nil, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Host a session", style: .default, handler: startHosting))
ac.addAction(UIAlertAction(title: "Join a session", style: .default, handler: joinSession))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(ac, animated: true)
}
func startHosting(action: UIAlertAction) {
guard let mcSession = mcSession else { return }
mcAdvertiserAssistant = MCAdvertiserAssistant(serviceType: "hms-project25", discoveryInfo: nil, session: mcSession)
mcAdvertiserAssistant?.start()
}
func joinSession(action: UIAlertAction) {
guard let mcSession = mcSession else { return }
let mcBrowser = MCBrowserViewController(serviceType: "hms-project25", session: mcSession)
mcBrowser.delegate = self
present(mcBrowser, animated: true)
}
func sendText(message: String) {
guard let mcSession = mcSession else { return }
if mcSession.connectedPeers.count > 0 {
let data = Data(message.utf8)
do {
try mcSession.send(data, toPeers: mcSession.connectedPeers, with: .reliable)
} catch {
let ac = UIAlertController(title: "Send error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
}
@objc func showPeers(action: UIAlertAction) {
let ac = UIAlertController(title: "Connected Peers", message: connectedPeers.joined(separator: ", "), preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}