Implemented complete TCA architecture for iOS and watchOS targets: - Authentication flow (Sign in with Apple + Yahoo OAuth) - OAuth token management with iCloud Key-Value Storage - Yahoo Fantasy Sports API client with async/await - Watch Connectivity for iPhone ↔ Watch data sync - Complete UI for both iPhone and Watch platforms Core features: - Matchup score display - Category breakdown with win/loss/tie indicators - Roster status tracking - Manual refresh functionality - Persistent data caching on Watch Technical stack: - The Composable Architecture for state management - Swift Concurrency (async/await, actors) - WatchConnectivity framework - Sign in with Apple - OAuth 2.0 authentication flow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
62 lines
2.1 KiB
Swift
62 lines
2.1 KiB
Swift
//
|
|
// XMLResponseDecoder.swift
|
|
// FantasyWatch
|
|
//
|
|
// Created by Claude Code
|
|
//
|
|
|
|
import Foundation
|
|
|
|
final class XMLResponseDecoder: NSObject, XMLParserDelegate {
|
|
private var currentElement = ""
|
|
private var currentValue = ""
|
|
private var elementStack: [String] = []
|
|
private var dataDict: [String: Any] = [:]
|
|
private var arrayStack: [[String: Any]] = []
|
|
|
|
func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T {
|
|
let parser = XMLParser(data: data)
|
|
parser.delegate = self
|
|
|
|
guard parser.parse() else {
|
|
throw NetworkError.decodingError(
|
|
NSError(domain: "XMLDecoder", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to parse XML"])
|
|
)
|
|
}
|
|
|
|
let jsonData = try JSONSerialization.data(withJSONObject: dataDict)
|
|
return try JSONDecoder().decode(T.self, from: jsonData)
|
|
}
|
|
|
|
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
|
|
currentElement = elementName
|
|
elementStack.append(elementName)
|
|
currentValue = ""
|
|
}
|
|
|
|
func parser(_ parser: XMLParser, foundCharacters string: String) {
|
|
currentValue += string.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
|
|
elementStack.removeLast()
|
|
|
|
if !currentValue.isEmpty {
|
|
let path = elementStack.joined(separator: ".")
|
|
dataDict[elementName] = currentValue
|
|
|
|
if !path.isEmpty {
|
|
dataDict[path + "." + elementName] = currentValue
|
|
}
|
|
}
|
|
|
|
currentValue = ""
|
|
}
|
|
}
|
|
|
|
// NOTE: This is a simplified XML decoder for POC purposes.
|
|
// The Yahoo Fantasy API returns complex nested XML structures.
|
|
// For production, we would need to implement more sophisticated parsing
|
|
// that handles arrays, nested objects, and the specific Yahoo XML schema.
|
|
// For now, we will parse the specific endpoints we need with custom logic.
|