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

SwiftUI中TwitchAPI批量请求内存泄漏问题求助

解决方案

1. 修正数据模型的错误定义

你的myFollower结构体中包含了pagination字段,这是错误的——Twitch API返回的分页游标是顶层响应的一部分,并非单个粉丝对象的属性。这个冗余字段会导致每条粉丝数据都占用额外内存,在数据量大时会显著增加内存消耗。修正后的模型如下:

struct myFollower: Codable {
    let followed_at: String
    let from_id: String
    let from_login: String
    let from_name: String
    let to_id: String
    let to_login: String
    let to_name: String
}

struct TwitchFollowersResponse: Codable {
    let data: [myFollower]
    let total: Int?
    let pagination: Pagination?
}

struct Pagination: Codable {
    let cursor: String?
}

2. 分批处理数据,避免内存累积

不要一次性将所有粉丝数据保存在内存数组中,而是每获取一批数据就立刻处理(如写入数据库、本地文件),处理完成后释放该批次的内存。改造后的async/await函数如下:

func fetchFollowersBatchByBatch(token: String, targetUserId: String, limit: Int = GlobalConstants.LOADING_LIMIT, batchHandler: @escaping ([myFollower], Int) async -> Void) async throws {
    var cursor: String? = nil
    var totalCount: Int? = nil
    var processed = 0
    
    repeat {
        // 构建请求URL,首次请求不带after参数
        var endpoint = "https://api.twitch.tv/helix/users/follows?to_id=\(targetUserId)&first=100"
        if let cursor = cursor {
            endpoint += "&after=\(cursor)"
        }
        
        var request = URLRequest(url: URL(string: endpoint)!)
        request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        request.addValue(GlobalConstants.CLIENT_ID, forHTTPHeaderField: "Client-ID")
        
        let (data, response) = try await URLSession.shared.data(for: request)
        
        // 验证响应状态
        guard let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 else {
            throw NSError(domain: "TwitchAPI", code: (response as? HTTPURLResponse)?.statusCode ?? -1, userInfo: [NSLocalizedDescriptionKey: "请求失败"])
        }
        
        // 解析数据
        let responseData = try JSONDecoder().decode(TwitchFollowersResponse.self, from: data)
        let batch = responseData.data.compactMap { $0 }
        
        // 记录总数量(仅首次请求获取)
        if totalCount == nil {
            totalCount = responseData.total
        }
        
        processed += batch.count
        // 回调处理当前批次数据,处理后该批次内存会被自动回收
        await batchHandler(batch, totalCount ?? processed)
        
        // 更新游标
        cursor = responseData.pagination?.cursor
    } while processed < limit && cursor != nil
}

3. 严格串行处理多用户请求

确保遍历多个用户时,逐个串行执行粉丝拉取逻辑,避免并发请求导致的内存叠加。示例代码:

func processMultipleUsers(token: String, userIds: [String]) async throws {
    for userId in userIds {
        try await fetchFollowersBatchByBatch(token: token, targetUserId: userId) { batch, total in
            // 在这里处理当前批次数据,比如写入CoreData或本地文件
            autoreleasepool {
                // 包裹处理逻辑,加速临时对象的内存释放
                print("处理用户\(userId)的\(batch.count)条粉丝,累计已处理\(total)条")
                // 执行写入/存储操作...
            }
        }
    }
}

4. 优化内存回收

  • 在批次数据处理逻辑外包裹autoreleasepool,强制回收JSON解析、数据转换过程中产生的临时对象。
  • 避免在闭包中捕获不必要的强引用,确保没有循环引用导致内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:25:18