已发布作品适用于单个对象,但不适用于对象数组 [英] Published works for single object but not for array of objects

查看:42
本文介绍了已发布作品适用于单个对象,但不适用于对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作可单独移动的对象.我能够为一个对象成功完成此操作,但是一旦将其放入数组中,这些对象将无法再移动.

I am trying to make individually moveable objects. I am able to successfully do it for one object but once I place it into an array, the objects are not able to move anymore.

型号:

class SocialStore: ObservableObject {
    @Published var socials : [Social]

    init(socials: [Social]){
        self.socials = socials
    }
}

class Social : ObservableObject{
    var id: Int
    var imageName: String
    var companyName: String
    @Published var pos: CGPoint

    init(id: Int, imageName: String, companyName: String, pos: CGPoint) {
        self.id = id
        self.imageName = imageName
        self.companyName = companyName
        self.pos = pos
    }

    var dragGesture : some Gesture {
        DragGesture()
            .onChanged { value in
                self.pos = value.location
                print(self.pos)
        }
    }
}

多张图片(未拖动的图片):

Multiple image (images not following drag):

struct ContentView : View {
    @ObservedObject var socialObject: SocialStore = SocialStore(socials: testData)

    @ObservedObject var images: Social = testData[2]

    var body: some View {
        VStack {
            ForEach(socialObject.socials, id: \.id) { social in
                Image(social.imageName)
                    .position(social.pos)
                    .gesture(social.dragGesture)
            }
        }
    }
}

单个图像(图像跟随手势):

Single image (image follow gesture):

struct ContentView : View {
    @ObservedObject var socialObject: SocialStore = SocialStore(socials: testData)

    @ObservedObject var images: Social = testData[2]

    var body: some View {
        VStack {
            Image(images.imageName)
                .position(images.pos)
                .gesture(images.dragGesture)
        }
    }
}

我希望单个物品能够自由移动.我看到坐标正在更新,但是每个图像的位置都没有.

I expect the individual items to be able to move freely . I see that the coordinates are updating but the position of each image is not.

推荐答案

首先,免责声明:以下代码并非复制粘贴的解决方案.它的唯一目标是帮助您理解挑战.解决问题的方式可能更有效,所以一旦了解问题,就花点时间考虑一下实现.

为什么视图不更新?: SocialStore 中的 @Publisher 仅在数组更改时才会发出更新.由于没有从阵列中添加或删除任何内容,因此不会发生任何事情.另外,由于数组元素是对象(而不是值),所以当它们更改位置时,数组保持不变,因为对对象的引用保持不变.请记住:类创建对象,结构创建.

Why the view does not update?: The @Publisher in SocialStore will only emit an update when the array changes. Since nothing is being added or removed from the array, nothing will happen. Additionally, because the array elements are objects (and not values), when they do change their position, the array remains unaltered, because the reference to the objects remains the same. Remember: Classes create objects, Structs create values.

我们需要一种制作商店的方法,以便在其元素中的某些内容发生更改时发出更改.在下面的示例中,您的商店将订阅其每个元素绑定.现在,您商品的所有已发布更新都将转发给您的商店发布者,您将获得所需的结果.

We need a way of making the store, to emit a change when something in its element changes. In the example below, your store will subscribe to each of its elements bindings. Now, all published updates from your items, will be relayed to your store publisher, and you will obtain the desired result.

import SwiftUI
import Combine

class SocialStore: ObservableObject {
    @Published var socials : [Social]
    var cancellables = [AnyCancellable]()

    init(socials: [Social]){
        self.socials = socials

        self.socials.forEach({
            let c = $0.objectWillChange.sink(receiveValue: { self.objectWillChange.send() })

            // Important: You have to keep the returned value allocated,
            // otherwise the sink subscription gets cancelled
            self.cancellables.append(c)
        })
    }
}

class Social : ObservableObject{
    var id: Int
    var imageName: String
    var companyName: String

    @Published var pos: CGPoint

    init(id: Int, imageName: String, companyName: String, pos: CGPoint) {
        self.id = id
        self.imageName = imageName
        self.companyName = companyName
        self.pos = pos
    }

    var dragGesture : some Gesture {
        DragGesture()
            .onChanged { value in
                self.pos = value.location
                print(self.pos)
        }
    }
}

struct ContentView : View {
    @ObservedObject var socialObject: SocialStore = SocialStore(socials: testData)

    var body: some View {
        VStack {
            ForEach(socialObject.socials, id: \.id) { social in
                Image(social.imageName)
                    .position(social.pos)
                    .gesture(social.dragGesture)
            }
        }
    }
}

这篇关于已发布作品适用于单个对象,但不适用于对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆