Swift-saveContext,tableView,scrollView和reloadRows问题?

问题描述

我有使用NSFetchedResultsController填充数据的tableView。单击单元格时,它将带您到该对象的detailViewController。并使用prepare(for :)将以下两个属性推进。

var coreDataStack: CoreDataStack!
var selectedGlaze: Glaze?

在detailView内,我有2个单元格。第一个是包含带有图像数组的scrollView的单元格:

import UIKit

protocol SwipedRecipeImageViewDelegate: class {
    func recipeImageViewSwiped(_ cell: RecipePhotoTableViewCell,selectInt: Int)
}

class RecipePhotoTableViewCell: UITableViewCell,uiscrollviewdelegate {
    
    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var pageControl: UIPageControl!
    
    // -
    
    var imagesArray: [Data] = []
    var selectedImageData: Int = 0
    
    // -
    weak var delegate: SwipedRecipeImageViewDelegate?
    // -
    
    override func awakeFromNib() {
        super.awakeFromNib()
        self.backgroundColor = .clear
        self.selectionStyle = .none
        
        scrollView.delegate = self
        
        scrollView.isUserInteractionEnabled = false // Allows didSelectAtRow:
        contentView.addGestureRecognizer(scrollView.panGestureRecognizer) // Allows Scrolling
    }
    
    
    override func layoutSubviews() {
        super.layoutSubviews()
        setimages()
        setoffsetX(pageNumber: selectedImageData)
    }
    
    
    func configureCell(section: Int,row: Int,images: [RecipeImage],arrayInt: Int,delegate: SwipedRecipeImageViewDelegate) {
        self.delegate = delegate
        
        selectedImageData = arrayInt
        
        for image in images {
            guard let imageData = image.recipeImageData else { return }
            imagesArray.append(imageData)
        }
    }
    
    
    @IBAction func pageChanged(_ sender: UIPageControl) {
        setoffsetX(pageNumber: sender.currentPage)
    }
    
    func setoffsetX(pageNumber: Int) {
        
        pageControl.currentPage = pageNumber
        let offsetX = contentView.bounds.width * CGFloat(pageNumber)
        dispatchQueue.main.async {
            UIView.animate(withDuration: 0.2,delay: 0,options: UIView.Animationoptions.curveEaSEOut,animations: {
                self.scrollView.contentOffset.x = offsetX
            },completion: nil)
        }
        
    }
    
    
    func setimages() {
        
        // Set Page Count:
        pageControl.numberOfPages = imagesArray.count
        // Set Frame For ImageViews + Scroll View:
        for index in 0..<imagesArray.count {
            let imageView = UIImageView()
            imageView.frame.size = contentView.bounds.size
            imageView.frame.origin.x = contentView.bounds.width * CGFloat(index)
            imageView.image = UIImage(data: imagesArray[index])
            imageView.contentMode = .scaleAspectFill
            imageView.layer.masksToBounds = true // Limits Frame Size
            
            scrollView.addSubview(imageView)
        }
        
        // Set ScrollView Size:
        scrollView.contentSize = CGSize(width: (contentView.bounds.width * CGFloat(imagesArray.count)),height: contentView.bounds.height)
        scrollView.delegate = self
    }
    
    // Set Page Number:
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
        self.pageControl.currentPage = Int(pageNumber)
        delegate?.recipeImageViewSwiped(self,selectInt: pageControl.currentPage)
    }

第二个单元格包含一个stackView及其一些标签,以显示图像显示的数据。它接受很多参数,然后设置textColor并更改一些标签。没什么好激动的,所以我没有包含代码

DetailViewController:

 override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("cellForRowAt: ",indexPath)
    switch indexPath.section {
    case sectionImage:  // Section 0:
        guard
            let images = selectedGlaze?.glazeImage,let glazeImageSelected = selectedGlaze?.glazeImageSelected // This is a Double
            else { return returnDefaultCell() }
        
        let imageArray = images.allObjects as! [RecipeImage] // Takes NSSet of relational data and changes it into an Array to be passed into the image cell.
        let imageSelected = Int(glazeImageSelected) // Double Converted to Int
        
        switch indexPath.row {
        case 0:
            let cell = returnRecipeImageCell()
            return configureRecipeImageCell(cell: cell,for: indexPath,imagesArray: imageArray,imageSelected: imageSelected)
            
        case 1:
            let cell = returnAtmosphereCell()
            return configureAtmosphereCell(cell: cell,imageSelected: imageSelected)
            
        default: return returnDefaultCell()
        }
    }
}

SwipedRecipeImageViewDelegate:

func recipeImageViewSwiped(_ cell: RecipePhotoTableViewCell,selectInt: Int) {
    selectedGlaze?.glazeImageSelected = Double(selectInt)
    coreDataStack.saveContext()
    dispatchQueue.main.async { // 
        self.tableView.beginUpdates() //
        let row1: IndexPath = [0,1] //
        self.tableView.reloadRows(at: [row1],with: .automatic) //
        self.tableView.endUpdates() //
    }
}

问题: 我遇到的问题是在调用recipeImageViewSwiped()之后,用正确的信息重新加载第二个要更新的单元格。在这里看到:https://imgur.com/a/fIYfehf

dispatchQueue.main.async块中的代码处于活动状态时,会发生这种情况。当该块被注释掉时,会发生以下情况:https://imgur.com/a/fYUVZKH-这是我所期望的。 (除了[0,1]的单元格未更新)。

具体来说,当tableView重新加载行[0,1]时,仅在该行[0,1]上调用cellForRowAt()。但是我不确定为什么[0,0]处的单元格连同图像会弹回到scrollView中显示的原始图像。

目标: 我的目标是在滚动后使带有scrollView的单元不闪烁。而且还可以保存上下文,以便对象可以保存选择数组中的哪个图像。然后使用新信息更新/重新加载第二个单元格所选图像,以便它可以正确更新其标签

编辑:

在layoutSubviews()中删除以下内容会产生以下影响:https://imgur.com/a/vwrZfus-看起来大部分都可以正常工作。但是仍然有一个奇怪的动画。

override func layoutSubviews() {
    super.layoutSubviews()
    setimages()
    //        setoffsetX(pageNumber: selectedImageData)
}

编辑2: 设置单元格的视图似乎完全是一个问题。连同布局子视图。

编辑3:

我在Bool: hasSetLayout添加一个layoutSubviews()一个开关,它似乎可以正常运行。 -但是,如果仍然有任何信息可以帮助我理解此问题,我将不胜感激。

var hasSetLayout = false

override func layoutSubviews() {
        super.layoutSubviews()
        switch hasSetLayout {
        case false: setimages(selectedPhoto: selectedImageData)
        default: break
        }
    }

解决方法

尝试重新加载没有动画的行:

import { Directive,HostBinding,AfterViewInit } from "@angular/core";
import { NgControl } from "@angular/forms";

@Directive({
  selector: "[appInput]"
})
export class InputDirective implements AfterViewInit {
  @HostBinding("type") readonly type = "number";

   value = 5;
 

  ngAfterViewInit(){
     setTimeout(()=>{this.control.control.setValue(this.value)})
  }

  constructor(private control: NgControl) {
    
  }

  public increment() {
    this.control.control.setValue(this.value++);
  }
  public decrement() {
    this.control.control.setValue(this.value--);
  }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...