- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我注意到使用 swiftUI 的 withAnimation{}
的 XCode 有一个奇怪的行为。
我创建了以下工作示例:
import SwiftUI
class Block: Hashable, Identifiable {
// Note: this needs to be a class rather than a struct
var id = UUID()
static func == (lhs: Block, rhs: Block) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.id)
}
}
struct ContentView: View {
@State private var blocks: [Block]
init() {
var blocks = [Block]()
/// generate some blocks here
blocks.append(Block())
blocks.append(Block())
blocks.append(Block())
self._blocks = State(initialValue: blocks)
}
var body: some View {
VStack {
ForEach(blocks, id: \.self) { block in
BlockRow(block: block) { b in
print("COMMENT THIS LINE OUT") // try commenting out this line -> XCODE won't build anymore
withAnimation {
self.blocks.remove(at: self.blocks.firstIndex(of: b)!)
}
}
}
}
}
}
struct BlockRow: View {
@State var block: Block
var onDelete: (Block) -> Void = {_ in}
var body: some View {
Text("<Block>")
.onTapGesture {
print("Tap block \(block.id)")
self.onDelete(block)
}
}
}
上面的例子按预期工作,如果你点击它被删除的 block 之一,下面的 block 将很好地滑动到空闲位置。
但是XCode在这里产生了一个警告,我不明白:
Result of call to 'withAnimation' is unused
事情变得更加困惑:只需在 withAnimation block 之前注释掉 print stamenet /* print("COMMENT THIS LINE OUT") */
XCode 将不再构建项目:
Failed to produce diagnostic for expression; please file a bug report
这是一个错误还是我的方法完全偏离了道路?
最佳答案
问题的根源在于 self.blocks.remove(at:)
返回一个您没有处理的值。如果您明确忽略该值,那么无论 print
与否,您的代码都会按预期工作。声明在那里。
withAnimation {
_ = self.blocks.remove(at: self.blocks.firstIndex(of: b)!)
}
Swift 有一个特性,即带有一行代码的闭包会返回该语句的值作为闭包的返回值。所以在这种情况下,如果不忽略 remove(at:)
的返回值它返回一个 Block
和 Block
然后成为 withAnimation
的返回类型关闭。
withAnimation
是这样定义的:
func withAnimation<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result
这是一个通用函数,它接受一个闭包。该闭包的返回类型决定了通用占位符的类型,而后者又决定了 withAnimation
的返回类型。自己。
所以,如果你不忽略 remove(at:)
的返回类型, withAnimation<Block>
函数将返回 Block
.
如果忽略 remove(at:)
的返回值,则该语句成为没有返回的语句(即返回 ()
或 Void
)。因此,withAnimation
函数变为 withAnimation<Void>
它返回 Void
.
现在,因为 BlockRow
的关闭删除print语句时只有一行代码,它的返回值是单条语句的返回值,现在是Void
:
BlockRow(block: block) { b in
withAnimation {
_ = self.blocks.remove(at: self.blocks.firstIndex(of: b)!)
}
}
这与闭包的类型匹配 BlockRow
期待它的onDelete
关闭。
在您的原始代码中,print
语句导致关闭 BlockRow
有 2 行代码,从而避免了 Swift 使用单行代码来确定闭包的返回类型的特性。您确实收到了警告,表明您没有使用 Block
从 withAnimation<Block>
返回的功能。 @Asperi 的回答通过分配 Block
修复了该警告。由 withAnimation<Block>
返回至_
.这与我建议的解决方案具有相同的效果,但它处理的是更高一级的问题,而不是问题的根源。
为什么编译器不提示你忽略了remove(at:)
的返回值? ?
remove(at:)
被明确设计为允许您丢弃返回的结果,这就是为什么您不会收到警告它返回的值您未处理的原因。
@discardableResult mutating func remove(at i: Self.Index) -> Self.Element
但是如您所见,这会导致您遇到令人困惑的结果。您使用的是 remove(at:)
好像它返回了 Void
,但它实际上是返回 Block
已从您的阵列中删除。然后,这会导致导致您的问题的整个事件链。
关于SwiftUI withAnimation 导致意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64192786/
我注意到使用 swiftUI 的 withAnimation{} 的 XCode 有一个奇怪的行为。 我创建了以下工作示例: import SwiftUI class Block: Hashable,
我想要一个仅在有条件的情况下可见的动画 View 。当我这样做时,我会出现不可预测的行为。特别是,在以下情况下,我希望在 onAppear 中调用一个永远重复的动画,无论它在何时何地初始化,它总是可以
我有一个基于某些状态的 swiftUI 动画: withAnimation(.linear(duration: 0.1)) { self.someState = newState } 上述动画
我在研究 Swift UI 的线性动画技术时发现,与我的预期相反,增加持续时间似乎并没有使动画发生得更慢。这是故意的吗?如果是这样,我该如何制作较慢的动画? 示例代码: struct ButtonVi
我有一个包含多个部分的 UITableView,部分的数量是动态的,也就是说,它们可以随时增加。在 TableView 上重新加载带有动画的部分,其中部分的数量没什么大不了的。我只是这样称呼: [no
我的目标是在将对象添加到@State 事件数组时控制动画类型。 withAnimation 仅在第一次附加到事件数组时发生。然后在附加追加时忽略它。 我目前正在 Xcode 11 beta 4 上运行
我有一个带有可拖动组件(“弹性”文本)的屏幕,当释放时会弹回一个非常突出的 Spring 动画。 有些文本是异步传入的(在本例中,使用 Timer),我希望它能够很好地淡入,同时 Springy 标签
比方说,我有一个像这样的简单个人资料屏幕: class Model: ObservableObject { @Published var isSignedIn = false
我收到了这个警告: 'UIView' may not respond to 'addSubview:withAnimation:' 产生该警告的代码行是这样的: [self.masterView ad
这是我的代码(来自 Core Data 教程): [eventsArray insertObject:event atIndex:0]; NSIndexPath *indexPath = [NSInd
我正在构建一个动画进度按钮,它显示下载进度,然后在下载完成后展开以显示按钮文本(有点像 App Store 按钮)。 我有一个自定义按钮 View ,它采用 @Binding 到外部进度 CGFloa
我看到在 iOS 9 中,setStatusBarHidden(_:withAnimation:) 现在已被弃用,文档说使用 [UIViewController prefersStatusBarHid
我有一个隐藏了状态栏的应用程序。在主视图中,我使用 UIButtons 加载 subview View 。出于某种原因, subview 显示时带有隐藏的状态栏,但是,UI View 不会为此进行调整
我的 Root View Controller 中有代码观察 -[UIApplication sharedApplication] 的 @"statusBarHidden" 属性并调整其 View 的
我是一名优秀的程序员,十分优秀!