I have watched Apple's WWDC 2021 video on how to write an iOS app with custom group activities, link here.
After watching this video I tried to write a simple app of my own, using UIKit instead of SwiftUI. It's a simple app that uses a UIAlert to add Strings to a UITableView. I wrote it using Xcode 13 beta 4 running on macOS Monterey beta 4. It seems to work fine on my MacBook but I don't have a device running iOS 15 beta 4 to test, and it won't work in the simulator. Hope to test it soon.
In the meantime, I thought I'd share the code. It's a simple app, and there is only one view controller, and here's the code in it:
//
// ViewController.swift
// ShareOrder
//
// Created by iOS 15 Programming on 28/07/2021.
//
import UIKit
import GroupActivities
class ViewController: UIViewController {
var orders: [String] = []
var groupSession: GroupSession<ShareOrder>?
var messenger: GroupSessionMessenger?
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
title = "ShareOrder"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "orderCell")
Task {
for await session in ShareOrder.sessions(){
configureGroupSession(session)
}
}
}
@IBAction func activateGroupActivity(_ sender: Any) {
ShareOrder().activate()
}
@IBAction func addOrder(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Order", message: "Add a new order", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) {
[unowned self] action in
guard let textField = alert.textFields?.first, let orderToSave = textField.text else {
return
}
self.orders.append(orderToSave)
if let messenger = messenger {
Task {
do {
try await messenger.send(orderToSave)
} catch {
print("Failed to send")
}
}
}
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
orders.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "orderCell", for: indexPath)
cell.textLabel?.text = orders[indexPath.row]
return cell
}
}
extension ViewController {
struct ShareOrder: GroupActivity {
var metadata: GroupActivityMetadata {
var metadata = GroupActivityMetadata()
metadata.title = NSLocalizedString("Share Order", comment: "Title of group activity")
metadata.type = .generic
return metadata
}
}
func configureGroupSession(_ groupSession: GroupSession<ShareOrder>) {
orders.removeAll()
self.groupSession = groupSession
let messenger = GroupSessionMessenger(session: groupSession)
self.messenger = messenger
Task.detached { [weak self] in
for await (message, _) in messenger.messages(of: String.self) {
await self?.handle(message)
}
}
groupSession.join()
}
func handle(_ message: String) {
self.orders.append(message)
self.tableView.reloadData()
}
}
You can download it here:
My questions are as follows:
.task
modifier. So I created an asynchronous task in viewDidLoad()
to configure the group activity session instead. Is this the proper way of doing things, or is there a better way?Have tested my app and it works!