Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >表达式的类型是不明确的,在自定义类的“`ForEach`‘over数组中没有更多的上下文

表达式的类型是不明确的,在自定义类的“`ForEach`‘over数组中没有更多的上下文
EN

Stack Overflow用户
提问于 2020-07-14 20:30:57
回答 1查看 1.8K关注 0票数 3

我知道有很多关于Type of expression is ambiguous without more context编译时错误的问题,但我读了很多,似乎不明白为什么会发生我的错误。

首先,我有

代码语言:javascript
运行
AI代码解释
复制
protocol ExpensePeriod: AnyObject, Identifiable, Hashable {
    associatedtype Period: ExpensePeriod
    
    var type: Calendar.Component { get set }
    var interval: DateInterval { get set }
    var start: Date { get }
    var end: Date { get }
    var expenses: FetchRequest<Expense> { get }
    
    static func array(from startDate: Date, to endDate: Date) -> [Period]
    
    init(from date: Date)
}

广告:

代码语言:javascript
运行
AI代码解释
复制
extension ExpensePeriod {
    
    var start: Date { interval.start }
    var end: Date { interval.end }
    var expenses: FetchRequest<Expense> {
        FetchRequest<Expense>(
            entity: Expense.entity(),
            sortDescriptors: [NSSortDescriptor(key: "datetime", ascending: false)],
            predicate: NSPredicate(
                format: "datetime > %@ AND datetime < %@",
                argumentArray: [start, end]
            )
        )
    }
    
    static func array(of timeComponent: Calendar.Component, from startDate: Date, to endDate: Date) -> [Self] {
        var currentDate = startDate
        var array = [Self(from: currentDate)]
        while !Calendar.current.dateInterval(of: timeComponent, for: currentDate)!.contains(endDate) {
            currentDate = Calendar.current.date(byAdding: timeComponent, value: 1, to: currentDate)!
            array.append(Self(from: currentDate))
        }
        return array
    }
    
    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.interval == rhs.interval
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(interval)
    }
}

然后:

代码语言:javascript
运行
AI代码解释
复制
final class ExpenseYear: ExpensePeriod {
    
    typealias Period = ExpenseYear
    
    var type: Calendar.Component
    var interval: DateInterval
    
    var year: Int { Calendar.current.component(.year, from: interval.start) }
    var expenseMonths: [ExpenseMonth] {
        return ExpenseMonth.array(from: start, to: end)
    }
    
    static func array(from startDate: Date, to endDate: Date) -> [ExpenseYear] {
        array(of: .year, from: startDate, to: endDate)
    }
    
    init(from date: Date) {
        self.type = .year
        self.interval = Calendar.current.dateInterval(of: type, for: date)!
    }
}

现在,主要的SwiftUI视图:

代码语言:javascript
运行
AI代码解释
复制
struct ListView: View {
    
    @Environment(\.managedObjectContext) private var managedObjectContext
    @FetchRequest(
        entity: Expense.entity(),
        sortDescriptors: [NSSortDescriptor(key: "datetime", ascending: false)]
    ) var expenses: FetchedResults<Expense>
    
    @State private var showingNewExpenseSheet = false
    @State private var showingPreferencesSheet = false
    
    private var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "YYYY MMM"
        return formatter
    }
    
    var body: some View {
        NavigationView {
            List {
                ForEach(ExpenseYear.array(from: expenses.last!, to: expenses.first!)) { expenseYear in
                    ForEach(expenseYear.expenseMonths) { expenseMonth in
                        MonthlyListView(expenseMonth)
                    }
                    Text("\(0)")
                }.onDelete(perform: deleteExpenseItem)
            }
            .navigationBarTitle("Expenses")
            .navigationBarHidden(true)
        }
    }
    
    func deleteExpenseItem(at offsets: IndexSet) {
        for index in offsets {
            let expense = expenses[index]
            managedObjectContext.delete(expense)
        }
        do {
            try managedObjectContext.save()
        } catch {
            print("Wasn't able to save after delete due to \(error)")
        }
    }
}

struct MonthlyListView: View {
    @Environment(\.managedObjectContext) private var managedObjectContext
    var expenseFetchRequest: FetchRequest<Expense>
    var expenses: FetchedResults<Expense> {
        expenseFetchRequest.wrappedValue
    }
    let expenseMonth: ExpenseMonth
    
    init(_ month: ExpenseMonth) {
        self.expenseMonth = month
        self.expenseFetchRequest = month.expenses
    }
    
    var body: some View {
        Section(header: Text("\(expenseMonth.month)")) {
            ForEach(expenses) { expense in
                ExpenseRowItemView(expense)
            }
        }
    }
}

ExpenseRowItemView只显示各种日期时间/备注项。

费用实体看起来如下:

Type of expression is ambiguous without more context似乎发生在ForEach(ExpenseYear.array(from: expenses.last!, to: expenses.first!))。我在Xcode 12测试版上。谢谢你的帮助。

(如果您想知道为什么我要经历所有这些麻烦,只是为了提供一个费用列表:我以前有一个函数,它贯穿每个费用的datetime,并构建一个嵌套的SwiftUI呈现的年数和月份结构(使用节,等等)。但是,我不认为这是一种可伸缩/高性能的方法,因为每次呈现视图时都会调用此函数,从而触及核心数据中的每个条目,所以我认为每个月列表都会处理自己的FetchRequest,并有自己的日期边界,这也会使动态视图更容易,比如“选择一个月来查看本月之前的事务列表”。如果还有更好的方法,请告诉我。)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-14 23:33:00

ExpensePeriod中,您似乎没有遵循ExpenseYear --您缺少startend变量(很可能是错误的来源,但很难说)

符合后,如果错误仍然存在,我将在循环中用Text替换Text视图,并且在找到错误源之前继续替换。

当您缺少关键字或格式化循环时,通常会发生此错误。大多数情况下,它只是意味着编译器无法解释您所写的内容。

我会解决这个问题,但是上面的代码缺少一些东西,可以通过复制和粘贴来运行它。

编辑:

所以您的问题在于forEach,因为如果您仔细注意,您的代码看起来像这个ForEach(ExpenseYear.array(from: expenses.last!, to: expenses.first!)),但是,开销定义为var expenses: FetchedResults<Expense>,其中这个数组中的每个项都是ExpenseYear数组中的Expense类型,您的头看起来像这个tatic func array(from startDate: Date, to endDate: Date) -> [ExpenseYear],第一个和第二个参数是Date类型的,但是您要传递一个Expense类型的项。expenses.last!返回一个Expense对象,这不是一个Date!因此,要解决这个问题,首先必须做一些类似于这个expenses.last!.datetime!的事情

所以将您的代码更改为

ForEach(ExpenseYear.array(from: expenses.last!.datetime!, to: expenses.first!.datetime!), id: \.id) { expense in

应该能解决你的问题。请记住以下几点

  1. 更改此代码以反映应用程序中的任何地方,我只在一个实例中对其进行了更改,因为我已经注释掉了其余的代码。

  1. Force解缠总是个坏主意,所以我建议您正确处理日期,但首先要注意打开日期。

而且,我知道您评论说我不需要在startend中实现ExpenseYear,但不幸的是,我无法在没有实现它们的情况下编译,所以我不得不这样做。

或者,您可以更改.array协议以接受Expense而不是Date,然后处理如何从对象Expense返回数组,以便您的协议看起来如下所示

代码语言:javascript
运行
AI代码解释
复制
static func array(from startExpense: Expense, to endExpense: Expense) -> [Period]

实现可以是这样的

代码语言:javascript
运行
AI代码解释
复制
static func array(from startExpense: Expense, to endExpense: Expense) -> [ExpenseYear] {
        guard let startDate = startExpense.datetime, let endDate = endExpense.datetime else {
            return []
        }
        
        return array(of: .year, from: startDate, to: endDate)
    }

在这里,您已经处理了防范零日期的问题,除了实现之外,您不需要更改任何东西(老实说,我更喜欢这种方法)。

我知道要实现第二个方法,您必须改变设置协议和其他东西的方式,所以您可以做的是将一个可选的Date传递给array,类似于这个static func array(from startExpense: Date?, to endExpense: Date?) -> [Period]

然后保护,打开它们,否则返回空数组。但是在您的.last循环中仍然存在解包装.firstForEach开销的问题。

祝其他人好运!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62907643

复制
相关文章
forEach在集合中的使用
任何类型Collection的可迭代 - 列表,集合,队列 等都具有使用forEach的相同语法。
崔笑颜
2020/06/08
3.7K0
Python中的数组类型
Python没有提供内置的数组类型,但是通过标准库array提供了array类支持数组的创建与使用,可以创建的数组类型包括整数、实数、Unicode字符等等,可以使用help()函数查看更完整的类型列表。 >>> from array import array >>> s = "Hello world" >>> sa = array('u', s) #创建可变字符串对象 >>> print(sa) array('u', 'Hello world') >>> print(sa.tostring())
Python小屋屋主
2018/04/16
3.9K0
【前端】iterable类型的 forEach方法
zhaokang555
2023/10/17
920
Java 类在 Tomcat 中是如何加载的?
https://www.cnblogs.com/xing901022/p/4574961.html
Java技术栈
2019/09/26
2.6K0
Java 类在 Tomcat 中是如何加载的?
TypeScript 中的数组类型定义
在 TypeScript 中声明和初始化数组也很简单,和声明数字类型和字符串类型的变量也差不多,只不过在指定数组类型时要在类型后面加上一个中括号 []
Qwe7
2022/03/19
5.6K0
创建自定义类的对象数组
CN_Simo
2017/12/26
2.4K0
创建自定义类的对象数组
foreach 引发的值类型与引用类型思考
用都知道的一句话概括:“引用类型在堆上,栈上只保存引用;值类型即可存放于栈上也可存放于堆上,值类型变量直接存储值本身”。
雪飞鸿
2018/09/05
7640
foreach 引发的值类型与引用类型思考
java中数组的下标的数据类型是_java返回数组下标
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/10
2.3K0
JS中forEach的坑
我们就按如下写了代码,但是却不能实现我们想要的结果,该方法最终会永远返回true。
码客说
2023/04/06
2.3K0
关于数组中forEach() 、map()、filter()、reduce()、some()、every()的总结
1、forEach() var arr = [1, 2, 3, 4]; arr.forEach((item, index, arr) = > { console.log(item) //结果为1,2,3,4 }) //forEach遍历数组,无返回值,不改变原数组,仅仅只是遍历、常用于注册组件、指令等等。 2、map() var arr = [1, 2, 3, 4]; arr.map((item, index, arr) = > { return item * 10 //新数组为1
前端迷
2018/10/29
1.2K0
C++中的数组类型操作
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
鲸落c
2022/11/28
1.6K0
python里[::-1]_python中的数组类型
当j缺省时,默认为len(alist), 即a[1:]相当于a[1:len(alist)]
全栈程序员站长
2022/09/22
1.6K0
函数表达式在JavaScript中是如何工作的?
在JavaScript中,函数表达式是一种将函数赋值给变量的方法。函数表达式可以出现在代码的任何位置,而不仅仅是函数声明可以出现的位置。函数表达式的语法如下:
王小婷
2023/10/23
4470
在没有DOM操作的日子里,我是怎么熬过来的(中)
前言 继上篇推送之后,在掘金、segmentfault、简书、博客园等平台上迅速收到了不俗的反馈,大部分网友都留言说感同身受,还有不少网友追问中篇何时更新。于是,闰土顺应呼声,在这个凛冽的寒冬早晨,将中篇热文滚烫呈上。 搬好小板凳,接下来,正文从这开始~ 在上篇的众多留言中,有位网友的评论比较具有代表性,摘出来供大家一阅: “ 同感啊楼主 比如做tab的时候,以前jq就是切换一下class,现在vue是切换数据,再根据数据显示class,这弯绕的啊 ” 当然,有评论就有回复,请看下面这位网友是怎么回复他的:
闰土大叔
2018/04/12
1.7K0
在没有DOM操作的日子里,我是怎么熬过来的(中)
【说站】js数组forEach方法的使用
1、forEach()类似于map(),它还将每个元素依次作用于传入函数,但不会返回新的数组。
很酷的站长
2022/11/26
2.9K0
【说站】js数组forEach方法的使用
在Excel中自定义上下文菜单(中)
在下面的示例中,将创建与上文描述的示例相同的按钮和子菜单,但使用RibbonX创建。
fanjy
2022/11/16
1.8K0
在Excel中自定义上下文菜单(中)
Java8 Lambda 表达式中的 forEach 如何提前终止?
也就是说,关键字"return",在这里执行的效果相当于普通for循环里的关键词continue"。
Spark学习技巧
2023/03/21
8740
Java8 Lambda 表达式中的 forEach 如何提前终止?
在PHP中灵活使用foreach+list处理多维数组
先抛出问题,有时候我们接收到的参数是多维数组,我们需要将他们转成普通的数组,比如:
硬核项目经理
2020/01/02
3.8K0
Java中的增强 for 循环 foreach
  foreach 是 Java 中的一种语法糖,几乎每一种语言都有一些这样的语法糖来方便程序员进行开发,编译期间以特定的字节码或特定的方式来对这些语法进行处理。能够提高性能,并减少代码出错的几率。在
IT可乐
2018/01/04
3.2K0
Java中的增强 for 循环   foreach
点击加载更多

相似问题

类数组错误-“类型的表达式是不明确的,没有更多的上下文”

11

表达式类型是不明确的,没有更多的上下文。

13

表达式的类型是不明确的,没有更多的上下文

13

在Swift中,表达式类型是不明确的,没有更多的上下文。

12

completionHandler -表达式类型是不明确的,没有更多的上下文

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档