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

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

ただいまの
回答率

90.51%

  • Swift

    7241questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

ストーリーボードを使わずにコードのみで値をラベルに渡す方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 165
退会済みユーザー

退会済みユーザー

FirstViewController(UIViewController)から
CollectionViewCell(UICollectionViewCell)へ値を渡す方法をコードのみでの実現したいと思っています。

一連の動作をする4ファイルのコードを記載しました。
ご確認いただければ幸いです よろしくお願いします。

import UIKit

class PresentationController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

private var Button: UIBarButtonItem!
    private let cellId = "cellId"

    override func viewDidLoad() {
        super.viewDidLoad()
        set()
    }

    func set() {

        collectionView?.delegate = self
        collectionView?.dataSource = self

        collectionView?.register(CollectionViewCell, forCellWithReuseIdentifier: "cellId")

    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        switch indexPath.item { 
        default:
            return collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CollectionViewCell

        }
    }

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

        switch indexPath.item {           
        default:
            return CGSize(width: view.frame.width, height: 300)
        }      
    }

    //ここへ
    @objc func openButton(_ sender: UIButton) {
        print("変更するモーダルビュー 開いたよ")
        //モーダルの動き .custom
        let modalViewController = FirstViewController()
        modalViewController.modalPresentationStyle = .custom
        modalViewController.transitioningDelegate = self
        present(modalViewController, animated: true, completion: nil)
    }

    //
    override func viewWillAppear(_ animated: Bool) {
        collectionView?.reloadData()
    }    
}
import UIKit

class FirstViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        set()
    }

    let userName: UITextField = {
        let un = UITextField()
        un.backgroundColor = .gray
        un.text = ""
        un.frame = CGRect(x: 100, y: 120, width: 200, height: 40)
        un.returnKeyType = .done
        return un
    }()

    let saveButton: UIButton = {
        let c = UIButton()
        c.frame = CGRect(x: 200, y: 0, width: 100, height: 100)
        c.setTitle("保存", for: .normal)
        c.backgroundColor = .gray
        return c
    }()

    let cancelbutton: UIButton = {
        let b = UIButton()
        b.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
        b.setTitle("キャンセル", for: .normal)
        b.backgroundColor = .green
        return b
    }()

    func set() {
        //初期化時 カラにする
        userName.text = ""
        view.addSubview(userName)
        userName.delegate = self

        view.addSubview(saveButton)
        //初期化時は タップ無効化
        saveButton.isEnabled = false
        //ターゲット このボタンをダイレクトにタップした時の判定は⬇️の パターン2にあるよ
        saveButton.addTarget(self, action: #selector(save2(_:)), for: .touchUpInside)

        view.addSubview(cancelbutton)
        cancelbutton.addTarget(self, action: #selector(close(_:)), for: .touchUpInside)
    }


    //パターン🏀
    //"return"をタップ キーボード閉じる
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {

        //"return"でtextFieldが閉じる(userName, place, siteなど)
        textField.resignFirstResponder()

        //TextFieldに入力された値に反応して、その値を習得。
        NotificationCenter.default.addObserver(self, selector: #selector(FirstViewController.changeNotifyTextField(sender:)), name: NSNotification.Name.UITextFieldTextDidChange, object: nil)

        return true
    }

    //senderの中に 変更があったUITextFieldが入ってくる感じ
    @objc public func changeNotifyTextField (sender: NSNotification) {

        guard let textView = sender.object as? UITextField else { return }

        //文字が1以上で有効に
        saveButton.isEnabled = (userName.text?.count)! > 0

        //タップ処理を登録
        saveButton.addTarget(self, action: #selector(save3(_:)), for: .touchUpInside)
    }

    //🏀

    //パターン🍯
    //saveButtonをダイレクトにタップ
    @objc func save2(_ sender: UITapGestureRecognizer) {

        NotificationCenter.default.addObserver(self, selector: #selector(FirstViewController.changeNotifyTextField2(sender:)), name: NSNotification.Name.UITextFieldTextDidChange, object: nil)
    }


    //senderの中に 変更があったUITextFieldが入ってくる感じ
    @objc public func changeNotifyTextField2 (sender: NSNotification) {

        guard let textView = sender.object as? UITextField else {
            return
        }
        //文字が1以上で有効に
        saveButton.isEnabled = (userName.text?.count)! > 0
        //タップ処理を登録
        saveButton.addTarget(self, action: #selector(save3(_:)), for: .touchUpInside)
    }


    @objc func save3(_ sender: UITapGestureRecognizer) {

        //値を渡したい
        let controller = presentingViewController as! CollectionViewCell

        controller.textFromModal = userName.text!

        self.dismiss(animated: true, completion: nil)

        print("タップ キーボードとモーダルビュー 閉じたよ")

        saveButton.endEditing(true)

    }
    //🍯
   @objc func close(_ sender: UITapGestureRecognizer) {
        print("保存キャンセル モーダルビュー 閉じたよ")
        self.dismiss(animated: true, completion: nil)
    }

}
import UIKit

class CollectionViewCell: UICollectionViewCell {

    //モーダルビューから受け取るテキスト
    var textFromModal = "" {
        didSet {
            // 値が更新されたら、ラベルの内容も更新する
            updateLabel(text: textFromModal)
        }
    }

    //ラベルの内容を更新する処理
    func updateLabel(text: String) {
        nameLabel.text = ""
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .gray
        set()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let button: UIButton = {
        let b = UIButton()
        b.setTitle("モーダル", for: .normal)
        b.backgroundColor = .blue
        b.translatesAutoresizingMaskIntoConstraints = false
        b.addTarget(self, action: #selector(PresentationController.openButton(_:)), for: .touchUpInside)
        b.frame = CGRect(x: 20, y: 50, width: 100, height: 100)
        return b
    }()


    let nameLabel: UILabel = {
        let l = UILabel()
        l.backgroundColor = .white
        l.translatesAutoresizingMaskIntoConstraints = false
        l.frame = CGRect(x: 20, y: 200, width: 200, height: 50)

        return l
    }()

    func set() {
        addSubview(button)
        addSubview(nameLabel)
    }    
}

//UIPresentationControllerで返す クラス名(CustomPresentationController)
extension PresentationController: UIViewControllerTransitioningDelegate {
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return CustomPresentationController(presentedViewController: presented, presenting: presenting)
    }

}

・追記
名称をSecondViewControllerからCollectionViewCellへ変更しました。紛らわしく申し訳ありません。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • fuzzball

    2018/06/19 15:43

    質問は何でしょうか?

    キャンセル

  • fuzzball

    2018/06/19 15:46

    クラス名が紛らわしいです。ViewControllerではないものに〜ViewControllerという名前を付けるのはやめましょう。(なんでViewControllerをセル登録してるの?と思ってしまいました)

    キャンセル

  • 退会済みユーザー

    2018/06/19 15:51

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

+1

ぱっと見アプリの目的が見えないので回答が難しいです。
UICollectionViewを使ったもので、その中の1セル(SecondViewController)のラベルを更新したいという質問だと認識しています。

※そもそもSecondViewControllerはViewControllerではありませんので、質問上このクラス名は混乱をもたらすだけです。

一般的にUICollectionViewを使うアプリでは、複数のセルを表示するにあたり、セルの元となるモデルクラス(String等の型でも良いですが)、そしてそれに対応するビューがあり、モデルの配列等をビューコントローラーで保持していると思います。

セル上のラベルを更新するには、元のモデルが持つ値を更新し、UICollectionViewに対し、セルのリロードを命令することで、セル上のラベルを更新します。
(ここまでの流れはストーリーボードの有無は関係無いはずです。)

提示していただいたコードには上記のような仕組みがないため、回答が困難です。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/19 16:29

    >>...認識しています。
    お聞きしたかったことは、ご指摘頂いた通りです。分かりづらくすみません。
    >>混乱をもたらすだけです。
    内容修正しました。

    ご教示いただいたUICollectionViewの仕組みは、まだ今の私では理解できませんでした。追って学習する際に参考にさせて頂きます。

    いったんUICollectionViewを使わず、UIViewControllerのみで同じようなラベルの更新を実践してみます。
    ありがとうございました。

    キャンセル

+1

なんか解決しちゃったみたいだけど書いておきますね。

FirstViewControllerのchangeNotifyTextField(sender:)の登録タイミングがおかしいです。
現状だと、リターンキーを押した後に登録しているので、文字を入力したときにchangeNotifyTextField(sender:)が呼ばれません。
ViewControllerの初期化時(viewDidLoad)に登録すればいいと思います。(changeNotifyTextField2(sender:)は不要になるはず)

あとは「値を渡したい」のところ、

let controller = presentingViewController as! CollectionViewCell

presentingViewControllerにはセルではなくPresentationControllerのインスタンスが入っています。直接セルにはアクセスできませんので、アクセスしたいセルを一旦PresentationControllerに保存するなど、工夫が必要です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/20 11:48

    fuzzball様 
    >>直接セルにはアクセスできませんので、
    など沢山の工夫すべき点アドバイスありがとうございます。
    登録タイミングについても、これから参考にさせて頂きます。

    キャンセル

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

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

関連した質問

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

  • Swift

    7241questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています