Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

swift - How can I update a UICollectionView from another class?

I am trying this for a couple of days now and haven't achieved anything yet. What I am trying to do is when a user picks a User item form the ViewController class, I want to save it in Realm and show it in the CollectionView of the SavedInterestsViewController class. I use a delegate pattern as suggested in this post How to access and refresh a UITableView from another class in Swift, but unfortunately I still receive nil, I guess because the GC removed the collectionView outlet already right? (please correct me if I misunderstood it). However, how can I get this to work by using a delegate pattern? Here is my code, this is the class where the user Picks a new User-item:

protocol ViewControllerDelegate {
func didUpdate(sender: ViewController)
}

class ViewController: UIViewController {

@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var collectionView: UICollectionView!
var delegate: ViewControllerDelegate?
let numberOfTweets = 5
let realm = try! Realm()

var image = UIImage()
var imageArray: [String] = []
var userArray: [User] = []

override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionCell")
    searchBar.delegate = self
}

}

extension ViewController: UISearchBarDelegate {

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    print("One second...")
    let functionClass = NetworkingFunctions()
    var loopCount = 0
    functionClass.getWikipediaAssumptions(for: searchBar.text!) { [self] (articleArray) in
        self.userArray.removeAll()
        for x in articleArray {
            functionClass.performWikipediaSearch(with: x, language: WikipediaLanguage("en")) { (user) in
                self.userArray.append(user)
                collectionView.reloadData()
                loopCount += 1
            }
        }
    }
}
}

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return userArray.count
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as! CollectionViewCell
    let image = UIImage.init(data: userArray[indexPath.item].image as Data)
    cell.userImage.image = image
    cell.nameLabel.text = userArray[indexPath.item].name
    cell.userImage.layer.borderColor = image?.averageColor?.cgColor
    if userArray[indexPath.item].checked == false {
        cell.checkmark.isHidden = true
    } else {
        cell.checkmark.isHidden = false
    }
    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if userArray[indexPath.item].checked == false {
        userArray[indexPath.item].checked = true
        collectionView.reloadData()
        let newUser = User()
        newUser.image = userArray[indexPath.item].image
        newUser.name = userArray[indexPath.item].name
        newUser.checked = true
        try! realm.write {
            realm.add(newUser)
        }
        self.delegate = SavedInterestsViewController()
        self.delegate?.didUpdate(sender: self)
    }
    else {
        userArray[indexPath.item].checked = false
        collectionView.reloadData()
    }
}
}

extension ViewController: UICollectionViewDelegateFlowLayout {

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = UIScreen.main.bounds.width/3 - 10
    let height = width
    return CGSize(width: width, height: height)
}

}

class User: Object {

@objc dynamic var image: NSData = NSData()
@objc dynamic var name: String = ""
@objc dynamic var checked: Bool = false

}

... and this is the class where I want to show the selected item, after the User clicked on the 'Back' Button of the navigation controller of the ViewController class:

class SavedInterestsViewController: UIViewController, ViewControllerDelegate {
func didUpdate(sender: ViewController) {
    DispatchQueue.main.async {
        self.collectionView.reloadData()
    }
}

@IBOutlet weak var addButton: UIBarButtonItem!
@IBOutlet weak var collectionView: UICollectionView!
let realm = try! Realm()

var userArray: [User] = []

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionCell")
    fetchDataFromRealm()
    
}

@IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
    performSegue(withIdentifier: "SavedToNew", sender: self)
}

func fetchDataFromRealm() {
    userArray.append(contentsOf: realm.objects(User.self))
    collectionView.reloadData()
}

}

extension SavedInterestsViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return userArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as! CollectionViewCell
    let image = UIImage.init(data: userArray[indexPath.item].image as Data)
    cell.userImage.image = image
    cell.nameLabel.text = userArray[indexPath.item].name
    cell.userImage.layer.borderColor = image?.averageColor?.cgColor
    if userArray[indexPath.item].checked == false {
        cell.checkmark.isHidden = true
    } else {
        cell.checkmark.isHidden = false
    }
    return cell
}
}

extension SavedInterestsViewController: UICollectionViewDelegateFlowLayout {

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = UIScreen.main.bounds.width/3 - 10
    let height = width
    return CGSize(width: width, height: height)
}

}
question from:https://stackoverflow.com/questions/65641920/how-can-i-update-a-uicollectionview-from-another-class

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

in your code you have lines

self.delegate = SavedInterestsViewController()
self.delegate?.didUpdate(sender: self)

but it do mostly nothing - you set the delegate to newly created class, didUpdate it - but I don't see any use of it - you don't present it in any way.

If I understand you right - you have SavedInterestsViewController, from it - you open ViewController, do something and when back to SavedInterestsViewController. (I can be wrong with your flow - correct me if so)

In this flow - you have delegate property in ViewController, but it must be of type SavedInterestsViewController. And you have to set it to SavedInterestsViewController when you open ViewController from it. And later in ViewController you have to call didUpdate method of delegate.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...