Section 11/161 menit
11. Integrasi dengan UIKit dan Non-SwiftUI
11. Integrasi dengan UIKit dan Non-SwiftUI
UIKit ViewController dengan Pipeline
swift
// UIKit search dengan async pipeline
final class SearchViewController: UIViewController {
private let searchChannel = AsyncChannel<String>()
private var pipelineTask: Task<Void, Never>?
private var tableView: UITableView!
private var results: [SearchResult] = [] {
didSet { tableView.reloadData() }
}
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
setupSearchBar()
startSearchPipeline()
}
private func startSearchPipeline() {
pipelineTask = Task { [weak self] in
guard let self else { return }
let pipeline = searchChannel
.debounce(for: .milliseconds(300))
.removeDuplicates()
for await query in pipeline {
guard !Task.isCancelled else { break }
do {
let results = try await SearchAPI.search(query: query)
await MainActor.run {
self.results = results
}
} catch {
await MainActor.run {
self.showError(error)
}
}
}
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if isMovingFromParent {
pipelineTask?.cancel()
searchChannel.finish()
}
}
}
extension SearchViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
Task { await searchChannel.send(searchText) }
}
}
extension SearchViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
results.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = results[indexPath.row].title
return cell
}
}
// MARK: - Placeholder
struct SearchResult: Identifiable { let id = UUID(); let title: String }
enum SearchAPI {
static func search(query: String) async throws -> [SearchResult] { [] }
}
Sensor / IoT Data Processing
swift
// Memproses data sensor dari Bluetooth atau IoT device
actor SensorProcessor {
private let dataChannel = AsyncChannel<SensorData>()
func ingestData(_ data: SensorData) async {
await dataChannel.send(data)
}
func startProcessing() async {
// Pipeline: group by 5 detik → hitung statistik → simpan
let pipeline = dataChannel
.chunked(by: .repeating(every: .seconds(5)))
for await window in pipeline {
let stats = calculateStats(Array(window))
await persistStats(stats)
}
}
private func calculateStats(_ readings: [SensorData]) -> SensorStats {
let values = readings.map(\.value)
return SensorStats(
count: readings.count,
average: values.reduce(0, +) / Double(values.count),
min: values.min() ?? 0,
max: values.max() ?? 0,
timestamp: Date()
)
}
private func persistStats(_ stats: SensorStats) async {
// simpan ke database
}
}
struct SensorData { let value: Double; let timestamp: Date }
struct SensorStats {
let count: Int; let average: Double
let min: Double; let max: Double; let timestamp: Date
}