我希望@StateObject
在返回后尽快取消初始化,但该对象似乎保存在内存中。“Deint ViewModel”没有打印在返回导航上,它是在我再次导航到我来自的视图后第一次打印的。有没有办法释放@StateObject
后退导航的内存?
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: TestView(), label: { Text("Show Test View") })
}
}
}
struct TestView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
Text("Test View")
}
}
final class ViewModel: ObservableObject {
deinit {
print("Deint ViewModel")
}
}
Run Code Online (Sandbox Code Playgroud) 我尝试在 Metal 和我的 swift 项目之间共享我在头文件中定义的枚举:
#ifndef SharedIndizes_h
#define SharedIndizes_h
#import <Foundation/Foundation.h>
#endif /* SharedIndizes_h */
typedef NS_ENUM(NSInteger, VertexAttribute)
{
VertexAttributePosition = 0,
VertexAttributeNormal = 1,
};
Run Code Online (Sandbox Code Playgroud)
#include <metal_stdlib>
#import "ExchangeTypes/SharedIndizes.h"
using namespace metal;
struct VertexIn {
float3 position [[ attribute(VertexAttributePosition) ]];
float3 normal [[ attribute(VertexAttributeNormal) ]];
};
Run Code Online (Sandbox Code Playgroud)
vertexDescriptor.attributes[VertexAttribute.position.rawValue]
vertexDescriptor.attributes[VertexAttribute.normal.rawValue]
Run Code Online (Sandbox Code Playgroud)
但我得到的只是一些意想不到的错误:
不支持的架构
未知类型名称“_int64_t”
未知类型名称“_int32_t”
...
从我的金属文件中删除#import "ExchangeTypes/SharedIndizes.h"
也会消除错误。
我有两个不同的视图,一个红色矩形和一个总是位于屏幕底部的黑色矩形。当我单击红色矩形时,它应该将自身定位在另一个矩形内。
目前,红色矩形是静态定位的:.position(x: self.tap ? 210 : 50, y: self.tap ? 777 : 50)
。有没有办法动态替换 210 和 777 到黑色矩形中心位置的位置?
我知道我可以使用 GeometryReader 来获取视图大小,但是如何使用该大小来定位不同的视图?这甚至是正确的方法吗?
struct ContentView: View {
@State private var tap = false
var body: some View {
ZStack {
VStack {
Spacer()
RoundedRectangle(cornerRadius: 10)
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .center)
}
.padding()
VStack {
ZStack {
Rectangle()
.foregroundColor(.red)
Text("Click me")
.fontWeight(.light)
.foregroundColor(.white)
}
.frame(width: 50, height: 50)
.position(x: self.tap ? 210 : 50, y: self.tap ? 777 : 50)
.onTapGesture …
Run Code Online (Sandbox Code Playgroud) 在 xcode 中使用内存图调试器时,我看到了一些内存泄漏。Backtrace 没有直接链接到我的任何代码,而是通过跟踪猜测它的保存以假设它与组合和一些 DataTaskPublisher 相关。
接下来我检查了 Instruments 内部,在那里我也看到了一些内存泄漏。所有泄漏都在堆栈跟踪中提到“专门的静态 UIApplicationDelegate.main()”,但它并没有真正链接到可能导致内存泄漏的东西。
删除负责从 API 加载数据的 ViewModel 可以消除泄漏。内存图调试器显示了一个 dataTaskPublisher,所以这有点道理。
import Foundation
import Combine
enum API {
static func games() -> AnyPublisher<[GameResult], Error> {
let requestHeaderGames = gamesRequest()
return URLSession.shared.dataTaskPublisher(for: requestHeaderGames)
.map(\.data)
.decode(type: [GameResult].self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
private static func gamesRequest() -> URLRequest {
let url = URL(string: "http://localhost:8080/api/games")!
var requestHeader = URLRequest.init(url: url)
requestHeader.httpBody =
"filter ..."
.data(using: .utf8, allowLossyConversion: false)
requestHeader.httpMethod = "POST"
requestHeader.setValue("application/json", forHTTPHeaderField: "Accept")
return requestHeader
} …
Run Code Online (Sandbox Code Playgroud) 我有一个带有可选的通用视图@ViewBuilder
。我想要两个初始值设定项,一个负责设置@ViewBuilder
,另一个应作为空的默认值。
struct OptionalViewBuilder<Content: View>: View {
let content: (() -> Content)?
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
init() {
self.content = nil
}
var body: some View {
VStack {
Text("Headline")
Divider()
content?()
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用 ViewBuilder 参数初始化视图,它当然可以工作。但是,当我使用空的初始化程序时,我收到错误消息:
无法推断通用参数“内容”
struct ContentView: View {
var body: some View {
OptionalViewBuilder {
Text("Text1")
Text("Text2")
}
OptionalViewBuilder() // <-- Generic parameter 'Content' could not be inferred
}
}
Run Code Online (Sandbox Code Playgroud)
我知道 Swift 在运行时需要显式类型,但是有没有办法让默认的初始化器工作呢?