如果我ObservableObject在 SwiftUI 中有一个,我可以将其称为@ObservedObject:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
Run Code Online (Sandbox Code Playgroud)
或者作为@StateObject:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
Run Code Online (Sandbox Code Playgroud)
但两者之间的实际区别是什么?有没有一种情况比另一种更好,或者它们是两种完全不同的东西?
在命令式 Swift 中,通常使用计算属性来提供对数据的便捷访问,而无需复制状态。
假设我有这个类用于命令式 MVC 使用:
class ImperativeUserManager {
private(set) var currentUser: User? {
didSet {
if oldValue != currentUser {
NotificationCenter.default.post(name: NSNotification.Name("userStateDidChange"), object: nil)
// Observers that receive this notification might then check either currentUser or userIsLoggedIn for the latest state
}
}
}
var userIsLoggedIn: Bool {
currentUser != nil
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
如果我想使用Combine 创建一个反应式等效项,例如用于SwiftUI,我可以轻松添加@Published到存储的属性以生成Publishers,但不能用于计算属性。
@Published var userIsLoggedIn: Bool { // Error: Property wrapper cannot be applied to a computed property
currentUser != …Run Code Online (Sandbox Code Playgroud) 使用以下代码:
struct HomeView: View {
var body: some View {
NavigationView {
List(dataTypes) { dataType in
NavigationLink(destination: AnotherView()) {
HomeViewRow(dataType: dataType)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当HomeView出现时,NavigationLink立即加载AnotherView. 结果,所有AnotherView依赖项也被加载,即使它在屏幕上还不可见。用户必须单击该行才能使其出现。MyAnotherView包含一个DataSource,在那里发生各种事情。问题是此时DataSource已加载整体,包括一些计时器等。
难道我做错了什么..?如何以这种方式处理它,AnotherView一旦用户按下它就会加载HomeViewRow?
每次应用程序启动时我都必须进行一些初始设置,但我收到错误:
错误很明显,答案却不是。我尝试将 init 放入子视图中,但我不能,它需要位于 root 中@main。我是这样定义的:
@StateObject private var amplifyConfig: AmplifyConfig = AmplifyConfig()
init() {
if(amplifyConfig.isAmplifyConfigured == false) {
amplifyConfig.dataStoreHubEventSubscriber()
amplifyConfig.configureAmplify()
}
}
Run Code Online (Sandbox Code Playgroud)
我如何摆脱该警告并实际实现它,这样它就不会创建多个实例,这就是我使用 @EnvironmentObject 的原因?
这可能与最近推出的新 (12.3) 版本的 XCode 相关,但我有一个非常简单的 SwiftUI 视图:
import SwiftUI
struct HomeView: View {
var body: some View {
NavigationView {
Text("Text")
.navigationBarTitle("My Title")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在控制台中收到此警告:
2020-12-15 18:25:06.506062-0800 Shopmatic[46177:9585655] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and …Run Code Online (Sandbox Code Playgroud) 我是 SwiftUI 新手,正在研究如何从 URL 下载图像。我发现在 iOS15 中你可以使用 AsyncImage 来处理图像的所有阶段。代码如下所示。
AsyncImage(url: URL(string: urlString)) { phase in
switch phase {
case .success(let image):
image
.someModifers
case .empty:
Image(systemName: "Placeholder Image")
.someModifers
case .failure(_):
Image(systemName: "Error Image")
.someModifers
@unknown default:
Image(systemName: "Placeholder Image")
.someModifers
}
}
Run Code Online (Sandbox Code Playgroud)
我会启动我的应用程序,每次我在列表上上下滚动时,它都会再次下载图像。那么我怎样才能添加缓存呢?我试图像在 Swift 中那样添加缓存。像这样的东西。
struct DummyStruct {
var imageCache = NSCache<NSString, UIImage>()
func downloadImageFromURLString(_ urlString: String) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
if let _ = …Run Code Online (Sandbox Code Playgroud) 我有一个 HStack:
struct BottomList: View {
var body: some View {
HStack() {
ForEach(navData) { item in
NavItem(image: item.icon, title: item.title)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如何以相等的间距将其内容完美地居中并自动填充整个宽度?
仅供参考,就像 Bootstraps CSS 类 .justify-content-around
所以我正在尝试学习 SwiftUI 和 Combine。我通常通过制作一个简单的小费计算器来开始新技术。
我似乎收到了一个随机的“通话中的额外参数”。编码时出错这是我的 SwiftUI 文件
import SwiftUI
internal enum ReceiptRowType {
case subtotal
case tax
case total
case tip
case grandTotal
}
struct TipView: View {
@ObservedObject internal var adBannerView: BannerAdView = BannerAdView()
@ObservedObject internal var receiptViewModel: ReceiptViewModel
private let percentageFormatter: NumberFormatter = {
let f = NumberFormatter()
f.numberStyle = .percent
return f
}()
var body: some View {
ZStack {
Color.white
.scaledToFit()
VStack {
if adBannerView.adHasLoaded {
adBannerView
.frame(maxHeight: adBannerView.adHeight)
.animation(.easeInOut(duration: 2.0))
}
BorderView()
Text(ARCHLocalizedStrings.receipt)
.foregroundColor(Color.gray)
BorderView() …Run Code Online (Sandbox Code Playgroud) 我正在创建一个 iOS 扫雷游戏,并希望在顶部有一个包含三条信息的栏:
然而,正如您在底部的图片中看到的那样,元素并不是均匀对齐的 - 我猜垫片自动具有相同的尺寸。因此,由于屏幕左侧的文本比右侧的文本宽,因此中间的文本会向右偏移。
如何对齐这些项目,使中心时间/图像与左侧/右侧的其他对象完全位于中间?
我的代码如下所示:
struct GameView: View {
@EnvironmentObject var game: Game
@State var labelHeight = CGFloat.zero
var body: some View {
VStack(alignment: .center, spacing: 10) {
Text("MINESWEEPER")
.font(.system(size: 25, weight: .bold, design: .monospaced))
.kerning(3)
.foregroundColor(.red)
HStack(alignment: .center, spacing: 5) {
Image(systemName: "rosette")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.black)
Text(game.highScoreString)
.font(.system(size: 15, weight: .bold, design: .monospaced))
.foregroundColor(.black)
Spacer()
Image(systemName: "timer")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.black)
Text(game.timerString)
.font(.system(size: 15, weight: .bold, design: .monospaced))
.foregroundColor(.black)
Spacer()
Image("top_bomb")
.resizable() …Run Code Online (Sandbox Code Playgroud) 我想知道目前是否有(在询问时,第一个 Xcode 12.0 Beta)使用@StateObject来自初始化程序的参数来初始化 a 的方法。
更具体地说,这段代码可以正常工作:
struct MyView: View {
@StateObject var myObject = MyObject(id: 1)
}
Run Code Online (Sandbox Code Playgroud)
但这不会:
struct MyView: View {
@StateObject var myObject: MyObject
init(id: Int) {
self.myObject = MyObject(id: id)
}
}
Run Code Online (Sandbox Code Playgroud)
从我理解的作用@StateObject是使视图成为对象的所有者。我使用的当前解决方法是传递已经初始化的 MyObject 实例,如下所示:
struct MyView: View {
@ObservedObject var myObject: MyObject
init(myObject: MyObject) {
self.myObject = myObject
}
}
Run Code Online (Sandbox Code Playgroud)
但是现在,据我所知,创建对象的视图拥有它,而这个视图没有。
谢谢。