Swift 根据数据动态加载UIController的部分

Swift 根据数据动态加载UIController的部分,swift,firebase,uicollectionview,uicollectionviewcell,Swift,Firebase,Uicollectionview,Uicollectionviewcell,我正在尝试在我的应用程序中为“添加朋友”页面实现UICollectionView,我需要以下功能: 当视图第一次出现时,显示用户可能有的好友请求 用户将用户名输入搜索栏,然后(如果找到)该用户名显示在好友请求单元格上方的单元格中 我一直试图通过使用UICollevtionViewController中的节来实现这一点,但这一直是一个令人头痛的问题 我正在使用firebase存储/获取我搜索的用户和任何好友请求。我可以在好友请求中看到用户 我面临的问题是: 动态显示部分(“添加朋友”部分和单元格

我正在尝试在我的应用程序中为“添加朋友”页面实现UICollectionView,我需要以下功能:

  • 当视图第一次出现时,显示用户可能有的好友请求

  • 用户将用户名输入搜索栏,然后(如果找到)该用户名显示在好友请求单元格上方的单元格中

  • 我一直试图通过使用UICollevtionViewController中的节来实现这一点,但这一直是一个令人头痛的问题

    我正在使用firebase存储/获取我搜索的用户和任何好友请求。我可以在好友请求中看到用户

    我面临的问题是:

  • 动态显示部分(“添加朋友”部分和单元格不应显示,除非用户搜索用户

  • 这个特定的用户(屏幕截图)有一个好友请求,但是没有填充单元格来显示这一点。我可以看到我正在正确地检索用户


  • 这样的集合视图是我处理此问题的最佳方式吗?似乎有点复杂。

    我说您的问题是状态。下面是一个如何使用带有关联值的枚举对状态建模的示例。请阅读有关枚举的详细信息

    import UIKit
    import Firebase
    
    
    class AddUserController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchBarDelegate {
    
    
        var searchedUser: User?
        var friendRequests = [User]()
        let cellId = "cellId"
        let headerId = "headerId"
    
    
        var sectionCategories = ["Add Friends", "Friend Requests"]
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            collectionView?.delegate = self
            collectionView?.dataSource = self
    
    
            collectionView?.register(SearchedUserCell.self, forCellWithReuseIdentifier: cellId)
            collectionView?.register(SectionHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
    
            getFriendRequests()
    
        }
    
        fileprivate func fetchSearchedUsers(username: String) {
            let ref = Database.database().reference().child("usernames")
    
            ref.child(username).observeSingleEvent(of: .value, with: { (snapshot) in
                // populate user info
                guard let uidOfSearchedUser = snapshot.value as? String else {return}
                Database.database().reference().child("users").child(uidOfSearchedUser).observeSingleEvent(of: .value, with: { (snapshot) in
    
                    guard let userDictionary = snapshot.value as? [String: Any] else {return}
                    self.searchedUser = User(uid: uidOfSearchedUser, dictionary: userDictionary)
                    self.collectionView?.reloadData()
                }, withCancel: { (err) in
                    print("error retrieving user", err)
                })
    
            }) { (err) in
                print("unable to find user: ", err)
            }
        }
    
        func getFriendRequests() {
            guard let uid = Auth.auth().currentUser?.uid else {return}
    
            Database.database().reference().child("users").child(uid).child("requests").observe(.value) { (snapshot) in
                guard let requestsDictionary = snapshot.value as? [String: Any] else {return}
                for (key, value) in requestsDictionary {
                    print(key, value)
                    Database.database().reference().child("users").child(key).observeSingleEvent(of: .value, with: { (snapshot) in
                        guard let userDictionary = snapshot.value as? [String: Any] else {return}
                        let user = User(uid: key, dictionary: userDictionary)
                        print("friend request from: ", user.username)
                        self.friendRequests.append(user)
                    })
                }
            }
            self.collectionView?.reloadData()
        }
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
            if section == 0 {
                return 4
            } else if section == 1 {
                return 1
            }
            return 0
        }
    
    
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
            let sendFriendRequestcell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
            let dealWithFriendRequestCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
    
            if indexPath.section == 0 {
                //Cell for searched user
                sendFriendRequestcell.user = searchedUser
                return sendFriendRequestcell
    
            } else if indexPath.section == 1 {
                //Populate all the friend requests that exist
    
                if friendRequests.count != 0 {
                    dealWithFriendRequestCell.user = friendRequests[indexPath.item]
                }
                return dealWithFriendRequestCell
            }
    
            return sendFriendRequestcell
    
        }
    
        override func numberOfSections(in collectionView: UICollectionView) -> Int {
            //Change this to return only 2 only if friend requests exist.
    
            return 2
        }
    
        override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    
            switch kind {
    
            case UICollectionElementKindSectionHeader:
    
                let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! SectionHeaderView
                headerView.sectionName = sectionCategories[indexPath.section]
                return headerView
    
            default:
                assert(false, "Unexpected element kind")
            }
    
        }
    
    }
    
    struct User {}
    struct UserRequest {}
    
    class Controller: NSObject {
        var collectionView: NSCollectionView!
    
        enum Sections: Int {
            case searched = 0
            case requests = 1
        }
    
        enum State {
            case none
            case requests(requests: [UserRequest])
            case searched(user: User)
            case searchedAndRequests(user: User, requests: [UserRequest])
        }
    
        var state: State = .none {
            didSet {
                collectionView.reloadData()
            }
        }
    }
    
    extension Controller: NSCollectionViewDataSource {
        func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
            switch state {
            case .requests(let requests):
                return requests.count
            case .searched(_):
                return 1
            case .searchedAndRequests(_, let requests):
                switch Section(rawValue: section)! {
                case .searched:
                    return 1
                case .requests:
                    return requests.count
                default:
                    fatalError("section not allowed.")
                }
            default:
                fatalError("invalid state.")
            }
        }
    
        func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
            // Create cell(s) here or later.
    
            switch state {
            case .searched(let user):
                // Populate user cell and return it.
                break
            case .requests(let requests):
                let request = requests[indexPath.item]
                // Populate cell with request and return it.
            case .searchedAndRequests(let user, let requests):
                switch Section(rawValue: indexPath.section)! {
                case .searched:
                    // Populate user cell and return it.
                    break
                case .requests:
                    let request = requests[indexPath.item]
                    // Populate cell with request and return it.
                default:
                    fatalError("section not allowed.")
                }
            default:
                fatalError("invalid state")
            }
        }
    
        func numberOfSections(in collectionView: NSCollectionView) -> Int {
            switch state {
            case .none:
                return 0
            case .requests(_), .searched(_):
                return 1
            case .searchedAndRequests(_, _):
                return 2
            }
        }
    }