You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift编译超时问题:分段选择器筛选SQLite查询报错求助

解决思路与优化方案

核心问题分析

  1. 变量作用域错误:你在switch的每个case里声明了局部的query变量,外部代码根本访问不到这个变量——而且类里定义的var query: NSURLQueryItem完全多余,和SQL查询的query不是同一概念,直接删掉即可。
  2. 代码冗余导致类型推断压力:每个case里的查询链式调用几乎完全重复,编译器要同时处理多个复杂的链式表达式,最终导致类型检查超时。

具体优化步骤

1. 清理无效属性

删掉类里的var query: NSURLQueryItem,这个属性和当前SQL查询逻辑无关,只会造成混淆。

2. 提取公共查询逻辑

把所有case里重复的select、order、limit部分抽出来,仅动态修改where条件,大幅减少代码冗余:

// 先定义基础查询,包含所有公共部分
let baseQuery = airports
    .select(airportId, codeIataAirport, nameAirportName, latitude, longitude)
    .order(codeIataAirport)
    .limit(100)

3. 明确变量类型,解决作用域问题

在switch外声明一个明确类型的查询变量,然后在case里仅修改where条件:

// 明确声明类型,帮助编译器快速完成类型推断
var filteredQuery: SQLite.Query = baseQuery

switch filterOption {
case "IATA":
    filteredQuery = baseQuery.where(codeIataAirport.like("\(text)%"))
case "ICAO":
    filteredQuery = baseQuery.where(codeICAOAirport.like("\(text)%"))
case "Airport Name":
    filteredQuery = baseQuery.where(
        codeIataCity.like("%\(text)%") || nameAirportName.like("%\(text)%")
    )
default:
    filteredQuery = baseQuery.where(
        codeIataAirport.like("%\(text)%") ||
        codeICAOAirport.like("%\(text)%") ||
        codeIataCity.like("%\(text)%") ||
        nameAirportName.like("%\(text)%")
    )
}

4. 拆分复杂初始化逻辑

把map里的Airport初始化逻辑抽成单独的辅助函数,减少单行代码复杂度,降低编译器类型检查压力:

// 辅助函数:从数据库行转换为Airport实例
private func airportFromRow(_ row: Row, 
                            airportId: Expression<Int?>,
                            nameAirportName: Expression<String?>,
                            codeIataAirport: Expression<String?>,
                            latitude: Expression<String?>,
                            longitude: Expression<String?>) -> Airport {
    return Airport(
        id: row[airportId] ?? .random(in: 11000...12000),
        name: row[nameAirportName] ?? "N/A",
        code: row[codeIataAirport] ?? "N/A",
        lat: row[latitude] ?? "0.0",
        long: row[longitude] ?? "0.0"
    )
}

之后在search函数里调用这个辅助函数:

return try db.prepare(filteredQuery).map { row in
    airportFromRow(row, 
                   airportId: airportId,
                   nameAirportName: nameAirportName,
                   codeIataAirport: codeIataAirport,
                   latitude: latitude,
                   longitude: longitude)
}

完整修改后的代码片段

import Foundation
import SQLite

class AirportsDataSource {
    
    var db: Connection?
    var filterOption: String = "IATA"

    init() {
        do {
            guard let fileURL = Bundle.main.url(forResource: "airports", withExtension: "sqlite") else {
                print("Could not find the airports.sqlite file in the app bundle.")
                return
            }
            db = try Connection(fileURL.path)
        } catch {
            print(error)
        }
    }
    
    func search(_ text: String) -> [Airport] {
        guard let db = db else { return [] }
        do {
            let airports = Table("mytable")
            let airportId = Expression<Int?>("airportId")
            let codeIataAirport = Expression<String?>("codeIataAirport")
            let codeICAOAirport = Expression<String?>("codeICAOAirport")
            let codeIataCity = Expression<String?>("codeIataCity")
            let nameAirportName = Expression<String?>("nameAirport")
            let latitude = Expression<String?>("latitudeAirport")
            let longitude = Expression<String?>("longitudeAirport")
            
            // 提取公共查询部分
            let baseQuery = airports
                .select(airportId, codeIataAirport, nameAirportName, latitude, longitude)
                .order(codeIataAirport)
                .limit(100)
            
            // 明确类型的查询变量
            var filteredQuery: SQLite.Query = baseQuery
            
            switch filterOption {
            case "IATA":
                filteredQuery = baseQuery.where(codeIataAirport.like("\(text)%"))
            case "ICAO":
                filteredQuery = baseQuery.where(codeICAOAirport.like("\(text)%"))
            case "Airport Name":
                filteredQuery = baseQuery.where(
                    codeIataCity.like("%\(text)%") || nameAirportName.like("%\(text)%")
                )
            default:
                filteredQuery = baseQuery.where(
                    codeIataAirport.like("%\(text)%") ||
                    codeICAOAirport.like("%\(text)%") ||
                    codeIataCity.like("%\(text)%") ||
                    nameAirportName.like("%\(text)%")
                )
            }
            
            // 调用辅助函数初始化Airport
            return try db.prepare(filteredQuery).map { row in
                airportFromRow(row, 
                               airportId: airportId,
                               nameAirportName: nameAirportName,
                               codeIataAirport: codeIataAirport,
                               latitude: latitude,
                               longitude: longitude)
            }
            
        } catch {
            print("error reading table", error)
            return []
        }
    }
    
    // 辅助函数:从数据库行转换为Airport实例
    private func airportFromRow(_ row: Row, 
                                airportId: Expression<Int?>,
                                nameAirportName: Expression<String?>,
                                codeIataAirport: Expression<String?>,
                                latitude: Expression<String?>,
                                longitude: Expression<String?>) -> Airport {
        return Airport(
            id: row[airportId] ?? .random(in: 11000...12000),
            name: row[nameAirportName] ?? "N/A",
            code: row[codeIataAirport] ?? "N/A",
            lat: row[latitude] ?? "0.0",
            long: row[longitude] ?? "0.0"
        )
    }
}

struct Airport: Equatable {
    let id: Int
    let name: String
    let code: String
    let lat: String
    let long: String
}

额外优化建议

把filterOption改成枚举类型,避免字符串硬编码,减少出错概率:

enum FilterOption: String {
    case iata = "IATA"
    case icao = "ICAO"
    case airportName = "Airport Name"
    case all
}

// 类里的属性改成:
var filterOption: FilterOption = .iata

之后switch直接使用枚举值,代码更安全易维护。

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:14:51