来自 UICollectionReusableView(Header) 自定义按钮的 PerformSegue Swift

PerformSegue from UICollectionReusableView(Header) custom button Swift

我有一个 headerView,其中有一个浮动按钮。由于浮动按钮中的所有子项都是以编程方式生成的,并且它是 headerView 的子视图,所以我无法调用 performSegue。我尝试创建一个委托方法,但我完全搞砸了。我知道协议可能是解决方法,但我不确定如何准确解决。 我在下面附上 headerView 的图片

headerView 代码:

class ProfileHeader: UICollectionReusableView, FloatyDelegate {

@IBOutlet weak var pname: UILabel!
@IBOutlet weak var pusername: UILabel!
@IBOutlet weak var profilePic: UIImageView!
@IBOutlet weak var userDesc: UILabel!
@IBOutlet weak var allviews: UILabel!
@IBOutlet weak var allphotos: UILabel!



var user : User!
var userposts = [String]()
var currentViewUser: String!
var floaty = Floaty()

let uid = KeychainWrapper.standard.string(forKey: KEY_UID)

override func awakeFromNib() {
    super.awakeFromNib()

    user = User()

    fetchCurrentUser()
    profilePic.addBlackGradientLayer(frame: profilePic.bounds)
    layoutFAB()
}




func layoutFAB() {

    floaty.openAnimationType = .slideDown
    floaty.hasShadow = false
    floaty.addItem("Edit Profile", icon: UIImage(named: "")) { item in
        // here is where the segue is to be performed.
    }

    floaty.paddingY = (frame.height - 50) - floaty.frame.height/2
    floaty.fabDelegate = self
    floaty.buttonColor = UIColor.white
    floaty.hasShadow = true
    floaty.size = 45

    addSubview(floaty)

}


func fetchCurrentUser(){
    if uid != nil {
        FBDataservice.ds.REF_CURR_USER.observeSingleEvent(of: .value, with: { (snapshot) in
            if let allData = snapshot.value as? Dictionary<String, Any> {
                if let cred = allData["credentials"] as? Dictionary<String, Any> {
                    let user = User(userid: snapshot.key, userData: cred)
                    self.pusername.text = user.username
                    self.pname.text = user.name
                    self.userDesc.text = user.aboutme
                    self.allphotos.text = String(user.photos)
                    self.allviews.text = String(user.views)
                    if user.userPic != nil {
                        let request = URL(string: user.userPic)
                        Nuke.loadImage(with: request!, into: self.profilePic)
                    } else {
                        return
                    }
                }
            }

        })
    }
}
}

CollectionViewController 代码:

class ProfileVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {


@IBOutlet weak var collectionView: UICollectionView!

var user : User!
var userposts = [String]()
var post = [Posts]()
var currentViewUser: String!
var imagePicker: UIImagePickerController!
var fetcher: Fetcher!
var imageFromImagePicker = UIImage()


let uid = KeychainWrapper.standard.string(forKey: KEY_UID)

override func viewDidLoad() {
    super.viewDidLoad()

    user = User()
    fetcher = Fetcher()
    imagePicker = UIImagePickerController()
    imagePicker.delegate = self

    collectionView.delegate = self
    collectionView.dataSource = self



    initializeUserPost()



    let nib = UINib(nibName: "ProfileCell", bundle: nil)
    collectionView.register(nib, forCellWithReuseIdentifier: "ProfileCell")





}


func editProfileTapped() {
    performSegue(withIdentifier: "manageconnections", sender: nil)
}

@IBAction func manageConnections(_ sender: Any) {
    performSegue(withIdentifier: "manageconnections", sender: nil)
}


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)
    collectionView.reloadData()
}


@IBAction func gotoSettings(_ sender: Any) {
    performSegue(withIdentifier: "openSettings", sender: nil)
}



@IBAction func newPost(_ sender: Any) {
    uploadNewPost()
}

@IBAction func backToFeed(_ sender: Any) {
    performSegue(withIdentifier: "feedroute", sender: nil)
}

@IBAction func searchUsers(_ sender: Any) {
    performSegue(withIdentifier: "searchNow", sender: nil)
}


func initializeUserPost() {

        FBDataservice.ds.REF_POSTS.observe(.value, with: { (snapshot) in
            if let snap = snapshot.value as? Dictionary<String, Any> {
                for snapy in snap {
                    if let userimages = snapy.value as? Dictionary<String, Any> {
                         let author = userimages["author"] as? String
                        if author! == self.uid! {
                            let images = userimages["imageurl"] as? String
                            self.userposts.append(images!)

                        }
                    }
                }
            }
            self.collectionView.reloadData()
        })


}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let userImages = userposts[indexPath.row]
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
    cell.fillCells(uid: uid!, userPost: userImages)
    return cell
}


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


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return userposts.count


}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {


        let selecteditem : String!
        selecteditem = userposts[indexPath.row]
        performSegue(withIdentifier: "lol", sender: selecteditem)

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "lol" {
        if let detailvc = segue.destination as? PhotoDetailVC {
            if let bro = sender as? String {
                detailvc.image = bro
            }
        }
    }
}


func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

     let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
    return view
}




func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let width = (collectionView.bounds.size.width/3) - 1
        print(width)
        let size = CGSize(width: width, height: width)
        return size

}

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

func collectionView(_ collectionView: UICollectionView, layout
    collectionViewLayout: UICollectionViewLayout,
                    minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

要解决您的问题,您应该使用名为 delegate 的模式。

代表意味着你需要一些东西来为你的 HeaderView 执行 segue 的工作,而不是一些可以做到的东西,在这种情况下你的 ProfileVC.

1 - 在您的 HeaderView 或其他文件中创建协议,由您决定。

2 - 在您的 HeaderView 中添加一个协议变量类型,并从您的 viewController.

中传递它
class ProfileHeader: UICollectionReusableView, FloatyDelegate {

@IBOutlet weak var pname: UILabel!
@IBOutlet weak var pusername: UILabel!
@IBOutlet weak var profilePic: UIImageView!
@IBOutlet weak var userDesc: UILabel!
@IBOutlet weak var allviews: UILabel!
@IBOutlet weak var allphotos: UILabel!

var user : User!
var userposts = [String]()
var currentViewUser: String!
var floaty = Floaty()

var delegate: HeaderViewDelegate!

let uid = KeychainWrapper.standard.string(forKey: KEY_UID)

override func awakeFromNib() {
    super.awakeFromNib()

    user = User()
    fetchCurrentUser()
    profilePic.addBlackGradientLayer(frame: profilePic.bounds)
    layoutFAB()
}

func setDelegate(delegate: HeaderViewDelegate) {
    self.delegate = delegate
}

func layoutFAB() {

    floaty.openAnimationType = .slideDown
    floaty.hasShadow = false
    floaty.addItem("Edit Profile", icon: UIImage(named: "")) { item in

         delegate.fabItemClicked()
    }

    floaty.paddingY = (frame.height - 50) - floaty.frame.height/2
    floaty.fabDelegate = self
    floaty.buttonColor = UIColor.white
    floaty.hasShadow = true
    floaty.size = 45

    addSubview(floaty)

}

func fetchCurrentUser(){
    if uid != nil {
        FBDataservice.ds.REF_CURR_USER.observeSingleEvent(of: .value, with: { (snapshot) in
            if let allData = snapshot.value as? Dictionary<String, Any> {
                if let cred = allData["credentials"] as? Dictionary<String, Any> {
                    let user = User(userid: snapshot.key, userData: cred)
                    self.pusername.text = user.username
                    self.pname.text = user.name
                    self.userDesc.text = user.aboutme
                    self.allphotos.text = String(user.photos)
                    self.allviews.text = String(user.views)
                    if user.userPic != nil {
                        let request = URL(string: user.userPic)
                        Nuke.loadImage(with: request!, into: self.profilePic)
                    } else {
                        return
                    }
                }
            }

        })
    }
}

public protocol HeaderViewDelegate {
     func fabItemClicked()
}

}

3 - 最后,编辑您的 ProfileVC 以实施 HeaderViewDelegate 协议并将其传递给您的 HeaderView

class ProfileVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, HeaderViewDelegate {

@IBOutlet weak var collectionView: UICollectionView!

var user : User!
var userposts = [String]()
var post = [Posts]()
var currentViewUser: String!
var imagePicker: UIImagePickerController!
var fetcher: Fetcher!
var imageFromImagePicker = UIImage()

let uid = KeychainWrapper.standard.string(forKey: KEY_UID)

override func viewDidLoad() {
    super.viewDidLoad()

    user = User()
    fetcher = Fetcher()
    imagePicker = UIImagePickerController()
    imagePicker.delegate = self

    collectionView.delegate = self
    collectionView.dataSource = self

    initializeUserPost()


    let nib = UINib(nibName: "ProfileCell", bundle: nil)
    collectionView.register(nib, forCellWithReuseIdentifier: "ProfileCell")

}

//Method from the new protocol
func fabItemClicked(){
//Perform your segue here.
} 

func editProfileTapped() {
    performSegue(withIdentifier: "manageconnections", sender: nil)
}

@IBAction func manageConnections(_ sender: Any) {
    performSegue(withIdentifier: "manageconnections", sender: nil)
}


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)
    collectionView.reloadData()
}


@IBAction func gotoSettings(_ sender: Any) {
    performSegue(withIdentifier: "openSettings", sender: nil)
}



@IBAction func newPost(_ sender: Any) {
    uploadNewPost()
}

@IBAction func backToFeed(_ sender: Any) {
    performSegue(withIdentifier: "feedroute", sender: nil)
}

@IBAction func searchUsers(_ sender: Any) {
    performSegue(withIdentifier: "searchNow", sender: nil)
}


func initializeUserPost() {

        FBDataservice.ds.REF_POSTS.observe(.value, with: { (snapshot) in
            if let snap = snapshot.value as? Dictionary<String, Any> {
                for snapy in snap {
                    if let userimages = snapy.value as? Dictionary<String, Any> {
                         let author = userimages["author"] as? String
                        if author! == self.uid! {
                            let images = userimages["imageurl"] as? String
                            self.userposts.append(images!)

                        }
                    }
                }
            }
            self.collectionView.reloadData()
        })


}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let userImages = userposts[indexPath.row]
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
    cell.fillCells(uid: uid!, userPost: userImages)
    return cell
}


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


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return userposts.count


}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {


        let selecteditem : String!
        selecteditem = userposts[indexPath.row]
        performSegue(withIdentifier: "lol", sender: selecteditem)

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "lol" {
        if let detailvc = segue.destination as? PhotoDetailVC {
            if let bro = sender as? String {
                detailvc.image = bro
            }
        }
    }
}


func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

     let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
     view.delegate = self
    return view
}




func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let width = (collectionView.bounds.size.width/3) - 1
        print(width)
        let size = CGSize(width: width, height: width)
        return size

}

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

func collectionView(_ collectionView: UICollectionView, layout
    collectionViewLayout: UICollectionViewLayout,
                    minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

不要忘记编辑此方法并将 self 传递给您的 HeaderView:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

     let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
     view.delegate = self
    return view
}