【问题标题】:PerformSegue from UICollectionReusableView(Header) custom button Swift来自 UICollectionReusableView(Header) 自定义按钮 Swift 的 PerformSegue
【发布时间】:2017-10-18 10:33:09
【问题描述】:

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

header查看代码:

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
}

【问题讨论】:

  • 你的代码在哪里?
  • 您要哪个代码?浮动按钮的处理程序?
  • 您的 headerView 将帮助我们
  • 问题已用代码更新
  • 您也可以添加您的 ViewController 代码吗?这是执行segue的地方

标签: ios swift xcode uicollectionview uicollectionreusableview


【解决方案1】:

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

委托意味着您需要为您的HeaderView 执行转场的工作,而不是可以执行此操作的工作,在这种情况下是您的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
}

【讨论】:

  • 非常感谢您的回答!我尝试实现它,它向我显示错误unexpectedly found nil while unwrapping an Optional value
  • 可能你的委托是空的,尝试使用 func setDelegate() 方法
  • 是的,我试过了。然而它在self.delegate.fabItemClicked() 上向我显示了同样的错误。添加header类后是否需要在ProfileVC中设置delegate=self
  • 是的,要查看委托是否为有效对象,请在您的 viewForSupplementaryElementOfKind 方法中放置一个断点,然后查看 view.delegate = self 是否正常工作。
  • 哇!有用。我将委托添加到 viewDidLoad()。对不起,代表对我来说不是很方便。不过我会明白的。好吧,它现在工作真棒。干杯队友
猜你喜欢
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多