【问题标题】:Value observers do not communicate correctly价值观察者没有正确沟通
【发布时间】:2020-09-10 17:48:12
【问题描述】:

点击手势由以下函数触发;

@objc func handleTapGR(tapGR: UITapGestureRecognizer) {
        let tapLocation = tapGR.location(in: nil)
        let moveNext = tapLocation.x > frame.width / 2 ? true : false

        moveNext ? userCards.nextImage() : userCards.previousImage()
    }

用户卡视图模型:

...        
    var imageIndex: Int = 0 { didSet{ imageIndexObserver?(imageIndex, userImages[imageIndex]) } }

    var imageIndexObserver: ((Int, UIImage) -> () )?
    mutating func nextImage() {
        imageIndex = imageIndex + 1 >= userImages.count ? 0 : imageIndex + 1
    }

    mutating func previousImage() {
        imageIndex = imageIndex - 1 < 0 ? userImages.count - 1  : imageIndex - 1
    }

索引改变时需要触发相关的闭包。 下面的对象在相关视图中。

var userCards: UserCardViewModel! {
        didSet{
            userCards.imageIndexObserver = { index, image in
                self.showingImage.image = self.userCards.userImages[index]
                print(index)                
           }
        }
    }

前两次点击时,我无法在索引语句上方打印。当我在图像上按下右侧时(相关数组计数为 2)

  • 第一次点击;什么都没有发生。
  • 第二次点击;打印 0。
  • 第三次,它打印 index = 1。

我正在这样初始化(来自相关的视图控制器)

convenience init(userCards: UserCardViewModel) {
        self.init(frame: .zero)
        self.userCards = userCards
        configure()
    }

【问题讨论】:

  • 你想在右击时增加imageIndex,在左击时减少...对吗??
  • 点击手势工作正常,只是值观察者不能正确通信。
  • 是的,因为我正在检查它是否工作正常.. 就像第一次 imageIndex 的初始值为 0。如果点击右侧,它将变为 1,如果我点击左侧的值,则第一次变成 3 (即 yourArray.count - 1)....那么你能告诉我你期望什么输出吗?
  • 让我们说 userImages.count = 2 我点击了右上角。我期望得到 index=2 但打印功能不起作用。
  • 如果您的数组计数为 2 并且您期望 imageIndex = 2,则应用程序将崩溃 bcoz 数组有 2 个计数并且您尝试访问第三个元素....array[2] 这将崩溃

标签: swift memory-management closures uitapgesturerecognizer observers


【解决方案1】:

我在视图中添加了手势。当您点击右侧索引计数会增加(左侧会减少),一旦达到数组计数,它将再次从 0 开始。

class ViewController: UIViewController {

    var userCards = UserCardViewModel() {
        didSet{
            userCards.imageIndexObserver = { index, image in
                //self.showingImage.image = self.userCards.userImages[index]
                print(index)        //<------- Here you will get index
           }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let img1 = UIImage(systemName: "arrow.up.right.video")
        let img2 = UIImage(systemName: "arrow.up.right.video")
        let img3 = UIImage(systemName: "arrow.up.right.video")

        userCards.userImages = [img1!,img2!,img3!]
        let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
        self.view.addGestureRecognizer(tap)
    }

    @objc func handleTap(_ tapGR: UITapGestureRecognizer) {
         let tapLocation = tapGR.location(in: nil)
         let moveNext = tapLocation.x > self.view.frame.width / 2 ? true : false
         moveNext ? userCards.nextImage() : userCards.previousImage()
     }
}

这是模型类

struct UserCardViewModel {

    var userImages : [UIImage] = []

    var imageIndex: Int = 0 {
        didSet {
            imageIndexObserver?(imageIndex, userImages[imageIndex])
        } }

    var imageIndexObserver: ((Int, UIImage) -> () )?

    mutating func nextImage() {
           imageIndex = imageIndex + 1 >= userImages.count ? 0 : imageIndex + 1
       }

    mutating func previousImage() {
           imageIndex = imageIndex - 1 < 0 ? userImages.count - 1  : imageIndex - 1
       }
}

最初imageIndex0

1) 开始时点击右侧imageIndex 将变为 1

2) 开始时点击左侧imageIndex 将变为 (yourArray.count - 1)

here下载演示

【讨论】:

  • 您的代码有效,我想这与我的结构有关,上面没有任何问题。让我清楚一点,我在 ViewController 中有数据,它用我上面提到的便利 init 初始化相关 View 中的 ViewModel 对象。当相关 View 中的 ViewModel 对象发生变化时,会触发 didSet{}。
猜你喜欢
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多