面试题答案
一键面试性能优化策略
- URL缓存:
- 使用
URLCache
类。可以设置一个共享的缓存实例,例如:
let cache = URLCache(memoryCapacity: 10 * 1024 * 1024, diskCapacity: 50 * 1024 * 1024, diskPath: nil) URLSession.shared.configuration.urlCache = cache
- 这样对于相同的URL请求,如果缓存中有有效的数据,就可以直接从缓存中获取,减少网络请求次数,提高性能。
- 使用
- 请求队列管理:
- 创建一个
OperationQueue
来管理URL请求操作。对于频繁的请求,可以根据优先级来安排请求顺序。例如,实时股票价格的请求优先级可以设置得较高。
let requestQueue = OperationQueue() requestQueue.maxConcurrentOperationCount = 3 // 限制并发请求数,避免过多请求占用过多资源
- 将URL请求封装成
URLSessionDataTask
,并作为Operation
添加到队列中。
- 创建一个
- 数据预取:
- 根据用户使用习惯,提前预取可能需要的数据。比如,如果用户经常在每天特定时间查看股票价格,可以在接近该时间时,提前发起请求获取数据,这样当用户实际查看时,数据已经准备好,减少等待时间。
复杂场景处理
- 网络延迟:
- 进度指示器:在发起URL请求时,在界面上显示进度指示器,告知用户请求正在进行。在SwiftUI中,可以使用
ProgressView
。
struct ContentView: View { @State private var isLoading = false var body: some View { VStack { if isLoading { ProgressView() } // 其他视图内容 } .onAppear { isLoading = true // 发起URL请求 } .onReceive(NotificationCenter.default.publisher(for:.urlRequestFinished)) { _ in isLoading = false } } }
- 超时处理:为URL请求设置合理的超时时间。在
URLSessionConfiguration
中设置,例如:
let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 10 // 设置请求超时时间为10秒 let session = URLSession(configuration: config)
- 进度指示器:在发起URL请求时,在界面上显示进度指示器,告知用户请求正在进行。在SwiftUI中,可以使用
- 重定向:
- 在
URLSession
的delegate
方法中处理重定向。可以创建一个自定义的URLSessionDelegate
类。
class CustomURLSessionDelegate: NSObject, URLSessionDelegate { func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { // 这里可以对重定向的请求进行处理,例如修改请求头 completionHandler(request) } } let session = URLSession(configuration: config, delegate: CustomURLSessionDelegate(), delegateQueue: OperationQueue.main)
- 在
- URL格式变化:
- URL解析与验证:在发起请求前,对URL进行解析和验证。可以使用
URLComponents
来构建和解析URL。
var components = URLComponents() components.scheme = "https" components.host = "example.com" components.path = "/api/stock" components.queryItems = [URLQueryItem(name: "symbol", value: "AAPL")] guard let url = components.url else { return }
- 版本控制:如果URL格式变化是由于API版本更新等原因,可以在请求头或URL参数中添加版本信息,服务器根据版本信息返回合适的数据格式。
- URL解析与验证:在发起请求前,对URL进行解析和验证。可以使用
设计模式
- MVVM(Model - View - ViewModel):
- Model:负责处理数据相关的逻辑,例如解析从URL获取的股票价格数据。可以创建一个
StockModel
类,其中包含股票价格、股票代码等属性以及解析数据的方法。
struct StockModel: Codable { let symbol: String let price: Double }
- View:在SwiftUI中,就是各种视图结构体,负责展示数据。例如,
StockView
展示股票价格。
struct StockView: View { @ObservedObject var viewModel: StockViewModel var body: some View { Text("Stock Price: \(viewModel.stock?.price?? 0)") } }
- ViewModel:作为View和Model之间的桥梁,负责发起URL请求、处理数据,并将数据传递给View。
class StockViewModel: ObservableObject { @Published var stock: StockModel? func fetchStockData() { // 发起URL请求,解析数据并更新stock属性 } }
- Model:负责处理数据相关的逻辑,例如解析从URL获取的股票价格数据。可以创建一个
- Singleton模式:
- 对于一些全局共享的资源,如
URLSession
实例或URLCache
实例,可以使用Singleton模式。这样可以确保整个应用中只有一个实例,避免资源浪费。
class NetworkManager { static let shared = NetworkManager() private init() {} let session = URLSession(configuration:.default) }
- 对于一些全局共享的资源,如
相关Swift框架
- URLSession:用于发起URL请求,处理与服务器的通信。它提供了多种类型的任务(如
URLSessionDataTask
、URLSessionUploadTask
等)来满足不同的需求。 - Combine:用于处理异步事件和数据流。可以将URL请求的结果通过
Publisher
和Subscriber
进行处理,实现更简洁的异步编程。例如,将URLSessionDataTask
的结果转换为Publisher
:extension URLSession { func dataTaskPublisher(for url: URL) -> URLSessionDataTaskPublisher { let request = URLRequest(url: url) return dataTaskPublisher(for: request) } func dataTaskPublisher(for request: URLRequest) -> URLSessionDataTaskPublisher { return URLSessionDataTaskPublisher(session: self, request: request) } } struct URLSessionDataTaskPublisher: Publisher { typealias Output = (data: Data, response: URLResponse) typealias Failure = URLError let session: URLSession let request: URLRequest func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input { let task = session.dataTask(with: request) { data, response, error in guard let data = data, let response = response else { let error = error?? URLError(.badServerResponse) subscriber.receive(completion:.failure(error)) return } subscriber.receive((data, response)) subscriber.receive(completion:.finished) } task.resume() } }
- Alamofire:虽然不是Swift标准库,但它是一个流行的网络请求框架,简化了URL请求的操作,提供了更友好的API。例如:
Alamofire.request("https://example.com/api/stock", method:.get, parameters: ["symbol": "AAPL"]).responseJSON { response in if let value = response.value { // 处理JSON数据 } }