小编sup*_*cio的帖子

SwiftUI 中的 ObservedObject 和 StateObject 有什么区别

如果我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)

但两者之间的实际区别是什么?有没有一种情况比另一种更好,或者它们是两种完全不同的东西?

ios swift swiftui

56
推荐指数
5
解决办法
9285
查看次数

SwiftUI:观察@Environment 属性变化

我试图使用 SwiftUI@Environment属性包装器,但我无法使其按预期工作。请帮助我理解我做错了什么。

例如,我有一个每秒生成一个整数的对象:

class IntGenerator: ObservableObject {
    @Published var newValue = 0 {
        didSet {
            print(newValue)
        }
    }

    private var toCanc: AnyCancellable?

    init() {
        toCanc = Timer.TimerPublisher(interval: 1, runLoop: .main, mode: .default)
            .autoconnect()
            .map { _ in Int.random(in: 0..<1000) }
            .assign(to: \.newValue, on: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

这个对象按预期工作,因为我可以看到控制台日志上生成的所有整数。现在,假设我们希望这个对象是一个可以从整个应用程序和任何人访问的环境对象。让我们创建相关的环境键:

struct IntGeneratorKey: EnvironmentKey {
    static let defaultValue = IntGenerator()
}

extension EnvironmentValues {
    var intGenerator: IntGenerator {
        get {
            return self[IntGeneratorKey.self]
        }
        set {
            self[IntGeneratorKey.self] = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以像这样访问这个对象(例如从视图中): …

ios swift swiftui

13
推荐指数
1
解决办法
4096
查看次数

@Published 属性包装器及其wrappedValue

当您定义自己的属性包装器时,您必须指定一个名为 'wrappedValue'非静态属性。例如:

@propertyWrapper
struct MyPropertyWrapper<Value> {
    var value: Value
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,编译器抱怨:

属性包装器类型“MyPropertyWrapper”不包含名为“wrappedValue”的非静态属性

因此,您只需执行以下操作即可修复错误:

@propertyWrapper
struct MyPropertyWrapper<Value> {
    var value: Value

    var wrappedValue: Value {
        get {
            value
        }
        set {
            value = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

只是举一些例子,这适用于@State

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper public struct State<Value> : DynamicProperty {

    /// The current state value.
    public var wrappedValue: Value { get nonmutating set }
}
Run Code Online (Sandbox Code Playgroud)

相同的@Binding

@available(iOS 13.0, OSX …
Run Code Online (Sandbox Code Playgroud)

ios swift swiftui

11
推荐指数
1
解决办法
1614
查看次数

UIViewController变量初始化

我正在研究这门swift语言,我对a中的变量初始化有疑问UIViewController.在我的DiagramViewController我有一些变数:

class DiagramViewController: UIViewController {

    var type: Constants.DiagramType
    var filename: String
    var numberOfBars: Int
    var numberOfSection: Int
    var diagramName: String

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}
Run Code Online (Sandbox Code Playgroud)

Swift需要这些var的init值,我可以通过多种方式实现,但是我应该如何在这些方式之间做出选择呢?

我可以初始化变量"inline":

class DiagramViewController: UIViewController {

    var type: Constants.DiagramType = Constants.DiagramType.HISTOGRAM
    var filename: String = "dd.txt"
    var numberOfBars: Int = 10
    var numberOfSection: …
Run Code Online (Sandbox Code Playgroud)

variables initialization uiviewcontroller ios swift

10
推荐指数
1
解决办法
5930
查看次数

SwiftUI中的自定义segue动画(导航动画)

在SwiftUI我们使用NavigationViewNavigationLink意见进行导航(我们习惯称之为segueUIKit)。UIKit中的标准segue是showsegue。在SwiftUI中,我们可以简单地执行以下操作:

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: Text("Destination")) {
                    Text("Navigate!")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

具有完全相同的效果(即使单词segue消失了)。

有时(实际上是经常),我们需要自定义segue动画。

  • 我们可以决定完全不对动画进行动画处理,实际上,在情节提要中,我们可以Animates通过单击动画来在属性检查器中找到该属性(true / false)。这样,目标视图控制器将立即代替源视图控制器出现。
  • 或者我们可以决定执行自定义动画。通常,这是通过实现符合UIViewControllerAnimatedTransitioning协议的对象来完成的。所有的魔术都发生在animateTransition使我们能够访问源视图控制器和目标视图控制器的方法中。

例如,一个简单的淡入淡出segue动画可能类似于:

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    UIView* containerView = [transitionContext containerView];
    UIViewController* fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController* toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    toVC.view.alpha = 0;
    [containerView addSubview:toVC.view];

    [UIView animateWithDuration:1 animations:^{
        toVC.view.alpha = 1;
        fromVC.view.alpha = 0;
    } completion:^(BOOL …
Run Code Online (Sandbox Code Playgroud)

animation uikit ios swift swiftui

9
推荐指数
1
解决办法
337
查看次数

SwiftUI:VStack/HStack/ZStack 拖动手势不起作用

我不明白为什么DragGesture在 VStack/HStack/ZStack 上不起作用。考虑以下简单示例:

struct ContentView: View {
    @State private var offset = CGSize.zero

    var body: some View {
        VStack {
            Text("Hello World!")
        }
        .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
        .edgesIgnoringSafeArea(.all)
        .offset(y: offset.height)
        .gesture(DragGesture()
            .onChanged { val in
                self.offset = val.translation
            }
            .onEnded { val in
                self.offset = .zero
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望整个视图根据offsetvar上下移动(由拖动手势改变)。但是,即使我写.gesture上的修饰VStack,甚至如果VStack是全屏幕(得益于.frame修改)拖动动作将不会在工作VStack。该手势仅在我拖动“Hello world”文本时有效,但如果我拖动到外部Text(但仍在全屏内部VStack)则无响应。有任何想法吗?谢谢。

ios swift swiftui

8
推荐指数
2
解决办法
2717
查看次数

可选的@ViewBuilder 闭包

在 SwiftUI 中是否可以有一个可选的@ViewBuilder闭包?例如,假设我想开发一个自定义视图,它采用两个视图构建器闭包,如下所示:

import SwiftUI

struct TopAndBottomView<Content>: View where Content: View {
    let topContent: () -> Content
    let bottomContent: () -> Content

    init(@ViewBuilder topContent: @escaping () -> Content, @ViewBuilder bottomContent: @escaping () -> Content) {
        self.topContent = topContent
        self.bottomContent = bottomContent
    }

    var body: some View {
        VStack {
            topContent()
            Spacer()
            bottomContent()
        }
    }
}

struct TopAndBottomView_Previews: PreviewProvider {
    static var previews: some View {
        TopAndBottomView(topContent: {
            Text("TOP")
        }, bottomContent: {
            Text("BOTTOM")
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

但我希望底部视图是可选的。我试过:

struct TopAndBottomView<Content>: …
Run Code Online (Sandbox Code Playgroud)

ios swift swiftui

8
推荐指数
2
解决办法
2364
查看次数

SwiftUI flashScrollIndicators

在 UIKit 中,我们有一个UIScrollView方法可以让滚动指示器短暂闪烁,以通知用户屏幕上有滚动内容(这并不总是很明显)。苹果说

func flashScrollIndicators()
Run Code Online (Sandbox Code Playgroud)

每当您将滚动视图置于前面时,您都应该调用此方法。

我的问题是:如何在 SwiftUI 上获得相同的效果?看一下这个非常愚蠢的例子,只是为了说明问题:

如果您看一下此屏幕,您将无法知道是否可以滚动某些内容:

在此输入图像描述

但你实际上可以:

在此输入图像描述

如何让用户意识到 SwiftUI 上的滚动内容?

uiscrollview ios swift swiftui

8
推荐指数
1
解决办法
1025
查看次数

用GIT忽略所有_notes目录

我需要你的帮助:我正在与另一个人一起开展一个网络项目.我正在使用NetBeans开发代码,而他正在使用Dreamweaver.我们想忽略所有Dreamweaver _notes目录(这些目录包含Dreamweaver自己生成的文件).我们不知道这些目录的确切路径.我们可以/a/b/c/_notes/f/_notes/a/b/c或在其他几十个地方找到它们.我们试图添加

/_notes/
/nbproject
configs/
Run Code Online (Sandbox Code Playgroud)

/_notes
/nbproject
configs/
Run Code Online (Sandbox Code Playgroud)

并且

*_notes*
/nbproject
configs/
Run Code Online (Sandbox Code Playgroud)

到.gitignore文件,但仍然跟踪_notes目录.有什么建议?先感谢您!

git dreamweaver gitignore

7
推荐指数
1
解决办法
2021
查看次数

SwiftUI中的@Binding和ForEach

我不能理解如何在SwiftUI @Binding中结合使用ForEach。假设我要Toggle根据布尔数组创建s 的列表。

struct ContentView: View {
    @State private var boolArr = [false, false, true, true, false]

    var body: some View {
        List {
            ForEach(boolArr, id: \.self) { boolVal in
                Toggle(isOn: $boolVal) {
                    Text("IsOn")
                }                
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道如何将绑定传递给数组中的布尔对象Toggle。上面的代码给出此错误:

使用未解决的标识符“ $ boolVal”

好的,这对我来说很好(当然)。我试过了:

struct ContentView: View {
    @State private var boolArr = [false, false, true, true, false]

    var body: some View {
        List {
            ForEach($boolArr, id: \.self) { boolVal in
                Toggle(isOn: boolVal) …
Run Code Online (Sandbox Code Playgroud)

data-binding binding ios swift swiftui

7
推荐指数
4
解决办法
1543
查看次数