解决Swift调用Google Books API时无作者书籍引发的崩溃问题
修复Google Books API Swift应用的崩溃问题
问题核心
崩溃的直接原因是let authors = i["volumeInfo"]["authors"].array!这一行的强制解包:当书籍没有作者信息时,array方法返回nil,使用!强制解包会直接触发运行时崩溃。此外代码中还有多处强制解包操作,都是潜在的崩溃风险点。
完整修复代码
import SwiftUI import SwiftyJSON import SDWebImageSwiftUI struct ContentView: View { var body: some View { NavigationView{ Home() .navigationTitle("Books") } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } struct Home: View { @ObservedObject var books = GetData() var body: some View { List(books.data) { book in HStack { if let imageUrl = URL(string: book.imurl), !book.imurl.isEmpty { WebImage(url: imageUrl) .resizable() .frame(width: 120, height: 170) .cornerRadius(10) } else { Image("book_thumbnail") .resizable() .frame(width: 120, height: 170) .cornerRadius(10) } VStack(alignment: .leading, spacing: 10) { Text(book.title) .fontWeight(.bold) Text(book.authors) Text(book.desc) .font(.caption) .lineLimit(4) .multilineTextAlignment(.leading) } } } } } class GetData: ObservableObject{ @Published var data = [Book]() init() { guard let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q=Harry+Potter&maxResults=40") else { print("Invalid URL") return } let session = URLSession(configuration: .default) session.dataTask(with: url) { [weak self] data, _, error in guard let self = self else { return } if let error = error { print("Request error: \(error.localizedDescription)") return } guard let jsonData = data else { print("No data received") return } guard let json = try? JSON(data: jsonData) else { print("Failed to parse JSON") return } guard let items = json["items"].array else { print("No items found in response") return } for item in items { let id = item["id"].stringValue let title = item["volumeInfo"]["title"].stringValue // 处理作者数组:nil时返回空数组,避免强制解包崩溃 let authorsArray = item["volumeInfo"]["authors"].array ?? [] // 将作者数组拼接为字符串,多个作者用逗号分隔 let authors = authorsArray.map { $0.stringValue }.joined(separator: ", ") // 没有作者时设置默认文本,保证界面有内容显示 let displayAuthors = authors.isEmpty ? "Unknown Author" : authors let description = item["volumeInfo"]["description"].stringValue let imurl = item["volumeInfo"]["imageLinks"]["thumbnail"].stringValue let url1 = item["volumeInfo"]["previewLink"].stringValue DispatchQueue.main.async { self.data.append(Book( id: id, title: title, authors: displayAuthors, desc: description, imurl: imurl, url: url1 )) } } }.resume() } } struct Book: Identifiable { var id : String var title : String var authors : String var desc : String var imurl : String var url : String }
关键修改说明
作者信息处理
- 把强制解包的
array!替换为array ?? [],用空数组替代nil,彻底避免崩溃 - 拼接作者字符串后,若结果为空则设置默认文本
Unknown Author,保证界面始终有内容显示
- 把强制解包的
移除所有强制解包操作
- URL创建用
guard let校验有效性,无效时输出日志而非崩溃 - JSON解析用
try?替代try!,解析失败时捕获错误并输出日志 - WebImage的URL创建用可选绑定,避免无效URL导致的潜在崩溃
- URL创建用
代码可读性优化
- 类名
getData改为GetData(符合Swift大驼峰命名规范) - 变量名
Books改为books、i改为book/item,提升代码辨识度 - 用
map + joined替代循环拼接作者字符串,代码更简洁高效
- 类名
内容的提问来源于stack exchange,提问作者AzAzinZ
相关产品推荐
相关产品推荐

