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

Swift中Operation间如何传递数据?我的实现遇异常

Swift Operation队列中操作间数据传递失败问题解决

问题描述

我正在学习Swift的Operation相关内容,能将一系列操作加入队列运行,但操作间传递数据时遇到问题:getVOOCSVData操作能正确获取数据(可通过其completionBlock中的打印语句确认),但后续的convertStringToArray操作运行时传入的数据为空。

原代码

操作配置代码

// operation setup
struct VOOModel {
    init() {
        let operationQueue = OperationQueue()
        let checkForUpdatedVOOData = IsUpdatedVOODataAvailable()
        checkForUpdatedVOOData.completionBlock = {
            print("Updated CSV Data = \(checkForUpdatedVOOData.updatedCSVData)")
            print("Latest Date = \(checkForUpdatedVOOData.latestCSVDate)")
        }
        let getVOOCSVData = GetVOOCSVData()
        getVOOCSVData.addDependency(checkForUpdatedVOOData)
        getVOOCSVData.completionBlock = {
            print("completion block get voo csv data")
            print("\(getVOOCSVData.csvData)") // prints out all of the data correctly
        }
        let convertStringToArray = ConvertStringToArray2(csvData: getVOOCSVData.csvData)
        convertStringToArray.addDependency(getVOOCSVData)
        convertStringToArray.completionBlock = {
            print("completion block convert string to array")
        }
        operationQueue.addOperations([checkForUpdatedVOOData, getVOOCSVData, convertStringToArray], waitUntilFinished: true)
    } // end init
} // end structure

ConvertStringToArray2类实现

// operation class
final class ConvertStringToArray2: Operation {
    var localData: String
    var sortedDataArray : [IndexFund] = []
    init(csvData: String) {
        localData = csvData
    }
    override func main() {
        var dataArray = [IndexFund]()
        var rows = localData.components(separatedBy: "\n")  // gives rows a value of 1
        rows.removeFirst()
        for row in rows {
            let columns = row.components(separatedBy: ",")
            if columns.count == 6 {
                let theDate = columns[0].replacingOccurrences(of: "-", with: "")
                let timeStamp = stringDateFormatter.date(from: theDate)!
                let open = Double(columns[1])!
                let high = Double(columns[2])!
                let low = Double(columns[3])!
                let close = Double(columns[4])!
                let theVolume = columns[5].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                let volume = Int64(theVolume)
                let fundValuesByDay = IndexFund(
                    timeStamp: timeStamp,
                    open: open,
                    high: high,
                    low: low,
                    close: close,
                    volume: volume!)
                dataArray.append(fundValuesByDay)
            }
            sortedDataArray = dataArray.sorted {
                $0.timeStamp < $1.timeStamp
            }
        }
    }
}

问题原因

初始化ConvertStringToArray2时直接传入getVOOCSVData.csvData,此时getVOOCSVData还未执行,csvData是空值。虽然通过addDependency保证了操作执行顺序,但初始化是同步完成的,依赖机制不影响初始化阶段的参数传递。

解决方案

方案一:修改操作类,持有前序操作引用

修改ConvertStringToArray2,让它持有getVOOCSVData的弱引用,在main方法中获取已赋值的数据:

final class ConvertStringToArray2: Operation {
    weak var csvDataOperation: GetVOOCSVData?
    var sortedDataArray : [IndexFund] = []
    
    init(operation: GetVOOCSVData) {
        csvDataOperation = operation
        super.init()
    }
    
    override func main() {
        guard let localData = csvDataOperation?.csvData, !localData.isEmpty else {
            print("CSV数据为空,无法转换")
            return
        }
        
        var dataArray = [IndexFund]()
        let rows = localData.components(separatedBy: "\n").dropFirst()
        
        for row in rows {
            let columns = row.components(separatedBy: ",")
            guard columns.count == 6,
                  let timeStamp = stringDateFormatter.date(from: columns[0].replacingOccurrences(of: "-", with: "")),
                  let open = Double(columns[1]),
                  let high = Double(columns[2]),
                  let low = Double(columns[3]),
                  let close = Double(columns[4]),
                  let volume = Int64(columns[5].trimmingCharacters(in: .whitespacesAndNewlines)) else {
                continue
            }
            
            let fundValuesByDay = IndexFund(
                timeStamp: timeStamp,
                open: open,
                high: high,
                low: low,
                close: close,
                volume: volume
            )
            dataArray.append(fundValuesByDay)
        }
        
        sortedDataArray = dataArray.sorted { $0.timeStamp < $1.timeStamp }
    }
}

同时修改操作初始化代码:

let convertStringToArray = ConvertStringToArray2(operation: getVOOCSVData)
convertStringToArray.addDependency(getVOOCSVData)

方案二:在前序操作完成后创建后续操作

修改getVOOCSVData的completionBlock,在数据准备完成后再创建并添加convertStringToArray操作:

struct VOOModel {
    init() {
        let operationQueue = OperationQueue()
        let checkForUpdatedVOOData = IsUpdatedVOODataAvailable()
        checkForUpdatedVOOData.completionBlock = {
            print("Updated CSV Data = \(checkForUpdatedVOOData.updatedCSVData)")
            print("Latest Date = \(checkForUpdatedVOOData.latestCSVDate)")
        }
        
        let getVOOCSVData = GetVOOCSVData()
        getVOOCSVData.addDependency(checkForUpdatedVOOData)
        
        getVOOCSVData.completionBlock = {
            print("completion block get voo csv data")
            print("\(getVOOCSVData.csvData)")
            
            guard !getVOOCSVData.csvData.isEmpty else { return }
            
            let convertStringToArray = ConvertStringToArray2(csvData: getVOOCSVData.csvData)
            convertStringToArray.completionBlock = {
                print("completion block convert string to array")
            }
            operationQueue.addOperation(convertStringToArray)
        }
        
        operationQueue.addOperations([checkForUpdatedVOOData, getVOOCSVData], waitUntilFinished: true)
    }
}

注意事项

  • 操作间传递数据时,避免在初始化阶段直接依赖未执行操作的属性,因为初始化是同步的,此时属性值还未被赋值
  • 方案一中使用weak引用前序操作,避免循环引用导致内存泄漏
  • 方案二更灵活,确保只有前序操作完成且数据有效时才创建后续操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:01:54