[Mac M2 Pro 12CPU, Ventura 13.6, iOS 17.0.3, Xcode 15.0]
選択した掲示板のスレッド一覧を表示させました。
掲示板のHTMLをパースして要素を取り出し、ChatGPTでC++の関数をSwiftへ変換して動作させました。FLTKに相当するViewについては自分で叩き台を考える必要があります。
Swiftの文法が分かっていればもっとスムーズに書けるはずですが、まあこれから学んでいきます。
次は選択スレッドの表示およびdatファイルの保存に関する実装に取り組みます。
import Foundation
import Kanna
struct Thread : Identifiable {
let id = UUID()
let threadID: String
let threadTitle: String
let threadNum: Int
}
func getThreads(url: String) async -> [Thread] { // urlはboard.url
var threads: [Thread] = []
var threadNumDict: [String: Int] = [:]
var threadNum = 0
let boardURL = url + "subback.html"
guard let url = URL(string: boardURL) else { return [] }
do {
let htmlString = try String(contentsOf: url, encoding: .shiftJIS)
guard let doc = try? HTML(html: htmlString, encoding: .shiftJIS) else { return [] }
for link in doc.xpath("//*[name()='small']/*[name()='a']") {
guard let id = link["href"], let title = link.text else { continue }
print(id)
let truncatedID = String(id.dropLast(4))
let idRegex = try! NSRegularExpression(pattern: "^[0-9]+$")
let idRange = NSRange(location: 0, length: truncatedID.utf16.count)
let isNumericID = idRegex.firstMatch(in: truncatedID, options: [], range: idRange) != nil
if !isNumericID {
continue
}
if threadNumDict[truncatedID] == nil {
threadNum += 1
threadNumDict[truncatedID] = threadNum
}
threads.append(Thread(threadID: truncatedID, threadTitle: title, threadNum: threadNumDict[truncatedID]!))
}
} catch {
print("Error: \(error)")
}
return threads
}
import SwiftUI
struct BoardView: View {
@State private var boardCategories: [BoardCategory] = []
var body: some View {
NavigationView {
VStack{
Text("板一覧")
List(boardCategories) { boardCategory in
DisclosureGroup(boardCategory.category) {
ForEach(boardCategory.boards) { board in
NavigationLink(destination: ThreadView(board: board)) {
ScrollView {
Text(board.name)
}
}
}
}
}
}
Spacer()
}
.padding()
.task {
boardCategories = await getBoards()
}
}
}
struct BoardView_Previews: PreviewProvider {
static var previews: some View {
BoardView()
}
}
import SwiftUI
struct ThreadView: View {
@State private var threads: [Thread] = []
var board: Board?
var body: some View {
VStack {
Text("スレッド一覧")
List{
ForEach(threads) { thread in
Text(thread.threadTitle)
}
}
Spacer()
}
.padding()
.task {
if let board = board {
threads = await getThreads(url: board.url)
}
}
}
}
struct ThreadView_Previews: PreviewProvider {
static var previews: some View {
ThreadView()
}
}