質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

FIrebaseでフォロー・アンフォローを実装したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 804

score 38

現在詰まっているところ

followボタンをクリックしprint("タップ")を出力したい

ボタンを設置しているファイル
UserProfileHeader.swift

import UIKit
import Firebase

class UserProfileHeader: UICollectionViewCell {

    // MARK: - Properties
    var delegate: UserProfileHeaderDelegate?

    var user: User? {

        didSet {

            // configure edit profile button
            configureEditProfileFollowButton()

            // set user stats
            setUserStats(for: user)

            let fullName = user?.name
            nameLabel.text = fullName

            profileImageView.loadImage(with: (user?.profileImageUrl)!)
        }
    }

    let profileImageView: UIImageView = {
        let iv = UIImageView()
        iv.contentMode = .scaleAspectFill
        iv.clipsToBounds = true
        iv.backgroundColor = .red
        return iv
    }()

    let nameLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 12)
        return  label
    }()



    let editProfileFollowButton: UIButton = {
        let button = UIButton(type: .system)
        button.layer.cornerRadius = 3
        button.layer.borderColor = UIColor.lightGray.cgColor
        button.addTarget(self, action: #selector(handleEditProfileFollow), for: .touchUpInside)
        button.layer.borderWidth = 0.5
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
        button.setTitleColor(.black, for: .normal)
        return button
    }()

    // MARK: - Handlers

    @objc func handleEditProfileFollow() {
        delegate?.handleEditFollowTapped(for: self)
    }






    func setUserStats(for user: User?) {

        guard let uid = user?.uid else { return }

        var numberOfFollowers: Int!
        var numberOfFollowing: Int!

        // get number of followers
        USER_FOLLOWER_REF.child(uid).observeSingleEvent(of: .value) { (snapshot) in

            if let snapshot = snapshot.value as? Dictionary<String, AnyObject> {
                numberOfFollowers = snapshot.count
            } else {
                numberOfFollowers = 0
                }

            let attributedText = NSMutableAttributedString(string: "\(numberOfFollowers!) \n", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)])
            attributedText.append(NSAttributedString(string: "followers", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14),
            NSAttributedString.Key.foregroundColor: UIColor.lightGray]))
            self.followersLabel.attributedText = attributedText
        }

        // get number of following

        USER_FOLLOWING_REF.child(uid).observeSingleEvent(of: .value) { (snapshot) in

            if let snapshot = snapshot.value as? Dictionary<String, AnyObject> {
                numberOfFollowing = snapshot.count
            } else {
                numberOfFollowing = 0
            }

            let attributedText = NSMutableAttributedString(string: "\(numberOfFollowing!) \n", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)])
            attributedText.append(NSAttributedString(string: "following", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14),
            NSAttributedString.Key.foregroundColor: UIColor.lightGray]))
            self.followingLabel.attributedText = attributedText
    }
    }

    func configureEditProfileFollowButton(){

        guard let currentUid = Auth.auth().currentUser?.uid else { return }
        guard let user = self.user  else { return }

        if currentUid == user.uid {
            // configure button as edit profile
            editProfileFollowButton.setTitle("テストプロフィールを編集", for: .normal)
        } else {
            // configure button as follow button
            editProfileFollowButton.setTitleColor(.white, for: .normal)
            editProfileFollowButton.backgroundColor = UIColor(red: 17/255, green: 154/255, blue: 237/255, alpha: 1)
            user.checkIfUserIsFollowed (completion: { (followed) in
                if followed {
                    self.editProfileFollowButton.setTitle("following", for: .normal)
                } else {
                    self.editProfileFollowButton.setTitle("follow", for: .normal)

                }
            })
        }
    }

    // MARK: - Init

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(profileImageView)
        profileImageView.anchor(top: self.topAnchor, left: self.leftAnchor, bottom: nil, right: nil, paddingTop: 16, paddingLeft: 12, paddingBottom: 0, paddingRight: 0, width: 80, height: 80)
        profileImageView.layer.cornerRadius = 80 / 2

        addSubview(nameLabel)
        nameLabel.anchor(top: profileImageView.bottomAnchor, left: self.leftAnchor, bottom: nil, right: nil, paddingTop: 12, paddingLeft: 12, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

        configureUserStats()

        addSubview(editProfileFollowButton)

        editProfileFollowButton.anchor(top: postsLabel.bottomAnchor, left: postsLabel.leftAnchor, bottom: nil, right: self.rightAnchor, paddingTop: 4, paddingLeft: 8, paddingBottom: 0, paddingRight: 12, width: 0, height: 30)

        configureBottomToolBar()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
後にUserProfile.swiftでフォロー・アンフォローを実装したいので、Protocolsファイルに設定
Protocols.swift


protocol UserProfileHeaderDelegate {

    func handleEditFollowTapped(for header: UserProfileHeader)

}
print("タップ")を実装したファイル
UserProfile.swift

import UIKit
import Firebase

private let reuseIdentifier = "Cell"
private let headerIdentifier = "UserProfileHeader"

class UserProfileVC: UICollectionViewController, UICollectionViewDelegateFlowLayout, UserProfileHeaderDelegate {


    // MARK: - Properties


    var currentUser: User?

    var userToLoadFromSearchVC: User?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

        self.collectionView!.register(UserProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier)

        self.collectionView.backgroundColor = .white

        if userToLoadFromSearchVC == nil {
            fetchCurrentUserData()
        }

    }


    // MARK: - UICollectionView

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return 0
    }

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

        // declare header
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as! UserProfileHeader

        // set delegate
        header.delegate = self



        if let user = self.currentUser {
            // UserProfileHeader のuser
            header.user = user
        } else if let userToLoadFromSearchVC = self.userToLoadFromSearchVC {
            header.user = userToLoadFromSearchVC
            navigationItem.title = userToLoadFromSearchVC.username
        }

        // return header
        return header
}
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: view.frame.width, height: 200)
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)

        // Configure the cell

        return cell
    }

    // MARK: - UserProfileHeader Protocol
    func handleEditFollowTapped(for header: UserProfileHeader) {     
        print("タップ")
    }

    //    MARK: - API
    func fetchCurrentUserData() {
        // set the user in header
        guard let currentUid = Auth.auth().currentUser?.uid else { return }

        Database.database().reference().child("users").child(currentUid).observeSingleEvent(of: .value) { (snapshot) in

            guard let dictionary = snapshot.value as? Dictionary<String, AnyObject> else { return }
            let uid = snapshot.key

            let user = User(uid: uid, dictionary: dictionary)
            self.currentUser = user
            self.navigationItem.title = user.username
            self.collectionView.reloadData()
    }
  }
}

イメージ説明

この状態でfollowボタンを押しても、Thread 1: breakpoint 2.1もコンソール上にも反応がありませんでした。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2019/02/19 16:38

    コードを変に省略しないで下さい。

    キャンセル

  • amazon_106

    2019/02/19 16:40

    編集します。

    キャンセル

回答 2

0

button.addTarget(self, action: #selector(handleEditProfileFollow), for: .editingChanged)

のforのあとを.touchUpInsideにしてください。
(あれ変わってた?)

@objc func handleEditProfileFollow() {

@objc func handleEditProfileFollow(_ sender: UIButton) {の方が良いかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/19 17:27

    あとはブレークポイント貼ってステップインなりすればすぐに判るかと。

    キャンセル

  • 2019/02/19 23:14

    すいません、handleEditProfileFollow()が呼ばれているかどうか、どうやって確かめればよいでしょうか。
    ググってみたんですが、検索ワードが悪いらしく有用そうなものが出てきませんでした。
    やり方を教えていただけないでしょうか。

    キャンセル

  • 2019/02/19 23:16

    ブレークポイントからステップインは、いろんな情報が出てきたのでそれを元にやってみます。

    キャンセル

check解決した方法

-1

UserProfileHeaderの

 var editProfileFollowButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Edit Profile", for: .normal)
        button.layer.cornerRadius = 3
        button.layer.borderColor = UIColor.lightGray.cgColor
        button.layer.borderWidth = 0.5
        button.addTarget(self, action: #selector(handleEditProfileFollow), for: .touchUpInside)

        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
        button.setTitleColor(.black, for: .normal)
        return button
    }()


の変数を
これを参考に

lazy var 


にしたら無事出力出来ました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/20 09:30

    ああ、なるほど、これってlazyが無いとselfを使っている時点でコンパイルエラーが出ていませんでしたか?

    キャンセル

  • 2019/02/20 21:43

    返信遅くなりました。
    出てなかったと思います。

    キャンセル

  • 2019/02/20 21:58

    UserProfileVC(実装の為のファイル)では出ました。
    ```
    // MARK: - UserProfileHeader Protocol
    func handleEditFollowTapped(for header: UserProfileHeader) {
    guard let user = header.user else { return }

    if editProfileFollowButton.titleLabel?.text == "Edit Profile"
    ```
    エラーメッセージはUse of unresolved identifier 'editProfileFollowButton'で
    header.editProfileFollowButton.titleLabel?.textとすることでエラーは消えました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る