现在开发者写程序,最方便的一点,就是不会的地方,可以问 Google
在 Google 中输入 Swift big5 to utf8 你会找到许多前人和你遇到一样的问题。
下面这个联结就是 Big5 转 UTF8 的范例文章。
http://supermingblog.blogspot.com/2015/04/ios-big5-to-utf8-or-utf8-to-big5.html
我参考了前人的程序码,扩充了 String
import Foundation
extension String {
static func dataWtihBig5(data: Data) -> Self? {
let big5Encoding = CFStringEncodings.big5_HKSCS_1999.rawValue
let convertEncodingBig5 = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(big5Encoding))
return String(data: data, encoding: String.Encoding(rawValue: convertEncodingBig5))
}
}
然後在 StockSubscriptionManager 那边,使用这个方法让 Data 转成 String,再喂给 CSVAdapter。
试着印出 csv.header 和其中一个 row,虽然怪怪的,但已经能读到中文了。
接下来继续解那个怪怪的 header。
下方是使用 csv 档的图,用 Spreadsheet, Excel, Number 打开,可以看到,在 header 上方还有一行,"公开申购公告-抽签日程表"。就是这一行,让 CSV 在 parse 的时候没有得到我们想要的结果。但这个套件没有从第 n 行开始读取的 api,那我们就要在 csv string 读取之前,把第 1 行拿掉。
从第 n 行开始读取这个职责,我归类在 CSVAdapter 里,所以 extension 一个 static func, CSVAdapter 可以得到去除掉第 n 行之前的 string
extension CSVAdapter {
/// 在公开资讯站拿到的 csv 档中,是有一些档案的 headers 不是从 line = 0开始,而是 line = 1 或其他行,用这个方以去掉
static func removeLine(_ rawString: String, at line: Int, separator: String = "\n") -> String {
let separatedString = rawString.components(separatedBy: separator)
let removedString = separatedString.suffix(from: line)
let joinedString = removedString.joined(separator: separator)
return joinedString
}
}
接下来,再小辐修改 StockSubscriptionManager 就可以了
//
// StockSubscriptionManager.swift
// ITIronMan
//
// Created by Marvin on 2021/9/4.
//
import Foundation
/// 这个类别专门处理股票申购资讯
class StockSubscriptionManager {
private lazy var alamofireAdapter: AlamofireAdapter = {
return AlamofireAdapter()
}()
func requestStockSubscriptionInfo(year: Int, completion: @escaping (([StockSubscriptionInfo], Error?) -> Void)) {
let urlString = "https://www.twse.com.tw/announcement/publicForm?response=csv&yy=\(year)"
alamofireAdapter.request(urlString, method: .get) { data, response, error in
if let error = error {
completion([], error)
return
}
var subscriptionList = [StockSubscriptionInfo]()
if let data = data,
let string = String.dataWtihBig5(data: data) {
let trimmedString = CSVAdapter.removeLine(string, at: 1)
if let csv = try? CSVAdapter(rawString: trimmedString) {
for each in csv.namedRows {
let stockCode = each["证券代号"] ?? ""
let stockName = each["证券名称"] ?? ""
let subscriptionStartString = each["申购开始日"] ?? ""
let subscriptionEndString = each["申购结束日"] ?? ""
let subscriptionOccurString = each["抽签日期"] ?? ""
let price = each["承销价(元)"] ?? ""
let actualPrice = each["实际承销价(元)"] ?? ""
let stockDeliveringDateString = each["拨券日期(上市、上柜日期)"] ?? ""
let stockCountString = each["申购股数"] ?? ""
let totalApplyCountString = each["实际承销股数"] ?? ""
let subscriptionRateString = each["中签率(%)"] ?? ""
let subscription = StockSubscriptionInfo(
stockCode: stockCode,
stockName: stockName,
subscriptionStartString: subscriptionStartString,
subscriptionEndString: subscriptionEndString,
subscriptionOccurString: subscriptionOccurString,
price: price,
actualPrice: actualPrice,
stockDeliveringDateString: stockDeliveringDateString,
stockCountString: stockCountString,
totalApplyCountString: totalApplyCountString,
subscriptionRateString: subscriptionRateString)
subscriptionList.append(subscription)
}
}
}
completion(subscriptionList, error)
}
}
}
台股申购 ViewController 所拥有的 model,只要呼叫年份,就完成了 model 的功能,将得到的申购列表回传 VC 的部分,则会放在下一篇。
//
// StockSubscriptionModel.swift
// ITIronMan
//
// Created by Marvin on 2021/9/4.
//
import Foundation
/// 股票申购 VC 所需的 Model
class StockSubscriptionModel {
private lazy var manager: StockSubscriptionManager = {
return StockSubscriptionManager()
}()
func requestStockSubscription() {
let year = 2021
manager.requestStockSubscriptionInfo(year: year) { subscriptionList, error in
// TODO: - 传出 list 给 vc
}
}
}
阵列点灯 ( 动画 ) 教学原文参考:阵列点灯 ( 动画 ) 这篇文章延续「阵列点灯 ( 显示图形 ...
外部中断 由於各种外设都可以有中断,今天我们就来实际使用一种比较简单的中断-外部中断,但却是非常重要...
TIMER+NVIC中断 今天我们来使用Timer的中断功能吧! 设定与昨天大致相同,只是我们现在需...
在电脑中的资料单位 1个0或1 =>一个位元(bit) 8个0或1 =>一个位元组(By...
如同前面介绍的,Flutter 定义了三种不同型别的Platform Channel 在platfo...