Open onmyway133 opened 2 years ago
We can use PropertyListEncoder from Swift 4
PropertyListEncoder
let encoder = PropertyListEncoder() encoder.outputFormat = .xml let data = try encoder.encode(model)
Or we can manually do with resultBuilder style
Declare @resultBuilder for PlistBuilder that can support if else check
@resultBuilder
PlistBuilder
if else
import Foundation @resultBuilder enum PlistBuilder { static func buildBlock(_ components: PlistNode...) -> [PlistNode] { components } static func buildBlock(_ components: [PlistNode]...) -> [PlistNode] { components.flatMap { $0 } } static func buildEither(first component: [PlistNode]) -> [PlistNode] { component } static func buildEither(second component: [PlistNode]) -> [PlistNode] { component } static func buildOptional(_ component: [PlistNode]?) -> [PlistNode] { component ?? [] } static func buildExpression(_ expression: PlistNode) -> [PlistNode] { [expression] } static func buildExpression(_ expression: [PlistNode]) -> [PlistNode] { expression } static func buildArray(_ components: [[PlistNode]]) -> [PlistNode] { components.flatMap { $0 } } } protocol PlistNode { func toLines() -> [String] } struct PlistString: PlistNode { let key: String let value: String init(key: String, value: String) { self.key = key self.value = value } func toLines() -> [String] { [ "<key>\(key)</key>", "<string>\(value)</string>" ] } } struct PlistBool: PlistNode { let key: String let value: Bool init(key: String, value: Bool) { self.key = key self.value = value } func toLines() -> [String] { let string = value ? "<true/>" : "<false/>" return [ "<key>\(key)</key>", "\(string)" ] } } struct PlistDict: PlistNode { var key: String? var nodes: [PlistNode] init(key: String? = nil, @PlistBuilder _ builder: () -> [PlistNode]) { self.key = key self.nodes = builder() } func toLines() -> [String] { var lines = [String]() if let key = key { lines.append("<key>\(key)</key>") } lines.append("<dict>") lines.append( contentsOf: nodes .flatMap { $0.toLines() } .map { Array(repeating: " ", count: 4) + $0 } ) lines.append("</dict>") return lines } func toPlistString() -> String { let content = toLines().joined(separator: "\n") return """ <?Plist version="1.0" encoding="UTF-8"?> <!DOCTYPE plist "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> \(content) </plist> """ } }
Then we can generate like
let dict = PlistDict { PlistBool(key: "uploadSymbols", value: exportOptions.uploadSymbols) PlistBool(key: "uploadBitcode", value: exportOptions.uploadBitcode) PlistBool(key: "compileBitcode", value: exportOptions.compileBitcode) PlistString(key: "signingStyle", value: exportOptions.signingStyle.rawValue) if let teamId = exportOptions.teamId { PlistString(key: "teamID", value: teamId) } if let signingCertificate = exportOptions.signingCertificate { PlistString(key: "signingCertificate", value: signingCertificate) } if let profiles = exportOptions.provisioningProfiles { PlistDict(key: "provisioningProfiles") { for profile in profiles { PlistString(key: profile.bundleId, value: profile.profileName) } } } }
We can use
PropertyListEncoder
from Swift 4Or we can manually do with resultBuilder style
Declare
@resultBuilder
forPlistBuilder
that can supportif else
checkThen we can generate like