所以我有一个GeometryReader封装了我大部分的contentView,
struct ContentView: View {
var body: some View {
GeometryReader { proxy in
....
}
}
}
但是我遇到了一个问题。我将它毫无问题地传递到ContentView中的各种视图中。但是由于某种原因,如果我尝试将其传递到应用程序中的if语句中定义的一组特定视图中,则会收到错误消息“编译器无法在合理的时间内对该表达式进行类型检查;请尝试将该表达式分解为不同的子表达式”。问题似乎源于向此视图添加更多变量(proxy,proxyOffsetTop或proxyOffsetBottom)(不知道为什么):
import Foundation
import SwiftUI
import Mapbox
struct SlideOverCard<Content: View>: View {
@ObservedObject var keyboardResponder = KeyboardResponder()
@GestureState private var dragState = DragState.inactive
@Binding var feedbackSubmitted: Bool
@Binding var position: CardPosition
var mapStyle: URL
//let proxy: GeometryProxy
var content: () -> Content
// var proxyOffsetTop: CGFloat
// var proxyOffsetBottom: CGFloat
var body: some View {
let drag = DragGesture()
.updating($dragState) { drag, state, transaction in
state = .dragging(translation: drag.translation)
}.onEnded(onDragEnded)
if (self.position == CardPosition.bottom(UIScreen.main.bounds.height - (77.5)) || self.position == CardPosition.middle(UIScreen.main.bounds.height - (135))) && mapStyle == MGLStyle.outdoorsStyleURL {
return VStack (spacing: 0) {
Handle(mapStyle: self.mapStyle)
self.content()
}
.frame(height: UIScreen.main.bounds.height)
.background(Color.white)
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.offset + self.dragState.translation.height - keyboardResponder.currentHeight)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
else if self.position == CardPosition.bottom(UIScreen.main.bounds.height - (77.5)) || self.position == CardPosition.middle(UIScreen.main.bounds.height - (135)) && mapStyle == MGLStyle.darkStyleURL {
return VStack (spacing: 0) {
Handle(mapStyle: self.mapStyle)
self.content()
}
.frame(height: UIScreen.main.bounds.height)
.background(Color.init(red: 15/255, green: 15/255, blue: 15/255))
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.offset + self.dragState.translation.height - keyboardResponder.currentHeight)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
else if mapStyle == MGLStyle.darkStyleURL {
return VStack (spacing: 0) {
Handle(mapStyle: self.mapStyle)
self.content()
}
.frame(height: UIScreen.main.bounds.height)
.background(Color.init(red: 15/255, green: 15/255, blue: 15/255))
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.offset + self.dragState.translation.height)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
else {
return VStack (spacing: 0) {
Handle(mapStyle: self.mapStyle)
self.content()
}
.frame(height: UIScreen.main.bounds.height)
.background(Color.white)
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.offset + self.dragState.translation.height)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
}
private func onDragEnded(drag: DragGesture.Value) {
let verticalDirection = drag.predictedEndLocation.y - drag.location.y
let cardTopEdgeLocation = self.position.offset + drag.translation.height
let positionAbove: CardPosition
let positionBelow: CardPosition
let closestPosition: CardPosition
if cardTopEdgeLocation <= CardPosition.middle(UIScreen.main.bounds.height - (135)).offset {
positionAbove = .top(50)
positionBelow = .middle(UIScreen.main.bounds.height - (135))
self.feedbackSubmitted = false
} else {
positionAbove = .middle(UIScreen.main.bounds.height - (135))
positionBelow = .bottom(UIScreen.main.bounds.height - (77.5))
self.feedbackSubmitted = false
}
if (cardTopEdgeLocation - positionAbove.offset) < (positionBelow.offset - cardTopEdgeLocation) {
closestPosition = positionAbove
} else {
closestPosition = positionBelow
}
if verticalDirection > 0 {
self.position = positionBelow
} else if verticalDirection < 0 {
self.position = positionAbove
} else {
self.position = closestPosition
}
}
}
enum RelativeCardPosition {
case top
case middle
case bottom
}
struct CardPosition: Equatable {
let relativeCardPosition: RelativeCardPosition
let offset: CGFloat
static func top(_ offset: CGFloat) -> CardPosition {
CardPosition(relativeCardPosition: .top, offset: offset)
}
static func middle(_ offset: CGFloat) -> CardPosition {
CardPosition(relativeCardPosition: .middle, offset: offset)
}
static func bottom(_ offset: CGFloat) -> CardPosition {
CardPosition(relativeCardPosition: .bottom, offset: offset)
}
}
enum DragState {
case inactive
case dragging(translation: CGSize)
var translation: CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return translation
}
}
var isDragging: Bool {
switch self {
case .inactive:
return false
case .dragging:
return true
}
}
}
一旦我将代理服务器从其传递给它的视图中删除,该应用程序就会正常运行。我尝试将不同的视图分组,因为我认为也许我达到了10视图的上限,但是我很确定这不再是错误...我不知道是什么原因引起的,有什么建议吗?
答案 0 :(得分:1)
这里,编译器的任务是找出结果视图类型。考虑到代码中有很多不同的情况,并且每种情况都可以返回不同的视图类型,因此这确实是一项艰巨的任务。我建议对这段代码进行少量重构。如我们所见,“只有两个参数取决于计算。所以:
private struct ContentParameters {
var backgroundColor: Color
var offsetY: CGFloat
}
private var contentParameters: ContentParameters {
if (self.position == CardPosition.bottom(UIScreen.main.bounds.height - (77.5)) || self.position == CardPosition.middle(UIScreen.main.bounds.height - (135))) && mapStyle == MGLStyle.outdoorsStyleURL {
return ContentParameters(
backgroundColor: .white,
offsetY: self.position.offset + self.dragState.translation.height - keyboardResponder.currentHeight
)
} else if self.position == CardPosition.bottom(UIScreen.main.bounds.height - (77.5)) || self.position == CardPosition.middle(UIScreen.main.bounds.height - (135)) && mapStyle == MGLStyle.darkStyleURL {
return ContentParameters(
backgroundColor: Color(red: 15/255, green: 15/255, blue: 15/255),
offsetY: self.position.offset + self.dragState.translation.height - keyboardResponder.currentHeight
)
} else if mapStyle == MGLStyle.darkStyleURL {
return ContentParameters(
backgroundColor: Color(red: 15/255, green: 15/255, blue: 15/255),
offsetY: self.position.offset + self.dragState.translation.height
)
} else {
return ContentParameters(
backgroundColor: .white,
offsetY: self.position.offset + self.dragState.translation.height
)
}
}
现在,由于我们已经移走了所有复杂的计算,因此可以使用以下代码来对代码进行一些清理:
var body: some View {
let drag = DragGesture() // this part stays the same
.updating($dragState) { drag, state, transaction in
state = .dragging(translation: drag.translation)
}.onEnded(onDragEnded)
let parameters = contentParameters // storing in a constant to not to calculate multiple times
return VStack (spacing: 0) { // using the real content from the original code
Handle(mapStyle: mapStyle)
content()
}
// Applying all the modifiers from the original code
.frame(height: UIScreen.main.bounds.height)
.background(parameters.backgroundColor) // using background color that was already calculated
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: parameters.offsetY) // using the offset that was alredy calcualted
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
我相信这将解决问题–编译器更容易理解生成的代码。另外一个好处是,我们获得了更多的SwiftUI动画友好代码(以防万一,如果您以后决定添加动画支持)。