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

Swift协议类型使用报错:需用'any'修饰TransactionListViewViewModelItemProtocol

问题分析与解决方案:Protocol作为类型使用需添加any关键字

问题场景

在实现Swift协议时触发编译错误,错误提示:Use of protocol 'TransactionListViewViewModelItemProtocol' as a type must be written 'any TransactionListViewViewModelItemProtocol'

相关代码

  1. 协议及实现结构体(TransactionListViewViewModelItem.swift):
protocol TransactionListViewViewModelItemProtocol: Comparable {
    var transactionBookingDate: Date { get }
    var transactionPartnerDisplayName: String { get }
}

struct TransactionListViewViewModelItem: TransactionListViewViewModelItemProtocol {

    static func < (lhs: TransactionListViewViewModelItem, rhs: TransactionListViewViewModelItem) -> Bool {
        return lhs.transactionBookingDate < rhs.transactionBookingDate
    }
    
    static func == (lhs: TransactionListViewViewModelItem, rhs: TransactionListViewViewModelItem) -> Bool {
        return lhs.transactionBookingDate == rhs.transactionBookingDate
    }
    
    var transactionBookingDate: Date {
        transactionModel.transactionDetail.bookingDate.getTransactionDate()
    }
    
    var transactionPartnerDisplayName: String {
        transactionModel.partnerDisplayName
    }
    
    private let transactionModel: Transaction
    
    // MARK: - init
    init(transaction: Transaction) {
        transactionModel = transaction
    }
}
  1. ViewModel中使用协议(TransactionListViewViewModel.swift):
protocol TransactionListViewViewModelProtocol {
    init(fileName: String)
    var numberOfRows: Int { get }
    func transactionItem(at indexPath: IndexPath) ->  TransactionListViewViewModelItemProtocol
}

class TransactionListViewViewModel: TransactionListViewViewModelProtocol {

    private var arrayOfTransactions: [TransactionListViewViewModelItemProtocol] = []
    // MARK: - init
    required init(fileName: String) {
        fetchAllTransactionsModel(from: fileName)
    }

  /*
   rest code....
  */
}

错误原因

从Swift 5.7版本开始,带有Self关联类型要求的协议(比如继承了Equatable/Comparable的协议,这两个协议都包含Self约束)作为类型使用时,必须显式添加any关键字标记为存在类型(existential type),明确告知编译器这是一个符合该协议的任意类型实例。

你的TransactionListViewViewModelItemProtocol继承了Comparable,自然带有Self关联类型要求,因此直接用协议作为类型会触发编译错误。

修复方案

将所有直接使用TransactionListViewViewModelItemProtocol作为类型的位置,替换为any TransactionListViewViewModelItemProtocol:

修改后的ViewModel协议代码:

protocol TransactionListViewViewModelProtocol {
    init(fileName: String)
    var numberOfRows: Int { get }
    func transactionItem(at indexPath: IndexPath) -> any TransactionListViewViewModelItemProtocol
}

修改后的ViewModel类代码:

class TransactionListViewViewModel: TransactionListViewViewModelProtocol {

    private var arrayOfTransactions: [any TransactionListViewViewModelItemProtocol] = []
    // MARK: - init
    required init(fileName: String) {
        fetchAllTransactionsModel(from: fileName)
    }

  /*
   rest code....
  */
}

修改后即可通过编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:55:15