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

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

新規登録して質問してみよう
ただいま回答率
85.35%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Q&A

解決済

1回答

1463閲覧

swift プロトコルが呼ばれません

退会済みユーザー

退会済みユーザー

総合スコア0

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

0グッド

0クリップ

投稿2020/08/13 02:48

編集2020/08/13 04:24

プロフィールページからプロフィール編集ページへモーダル表示をしています。プロフィールを編集してモーダルを閉じた時に即座に変更点がプロフィールに反映されないためプロトコルを用いて変更をすぐに反映させようとしていますが、できません。

EditProfileViewController.swift

import UIKit import NCMB import NYXImagesKit import PKHUD protocol ProfileEditDelegate { func didEditProfile(profileText: String) } class EditProfileViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet var mainImageView: UIImageView! @IBOutlet var subImageCollectionView: UICollectionView! @IBOutlet var selectMainImageButton: UIButton! @IBOutlet var displayNameTextField: UITextField! @IBOutlet var searchIdTextfield: UITextField! @IBOutlet var profileTextView: UITextView! @IBOutlet var logOutButton: UIButton! override func viewDidLoad() { super.viewDidLoad() if let user = NCMBUser.current(){ displayNameTextField.text = user.object(forKey: "userName") as? String searchIdTextfield.text = user.object(forKey: "searchId") as? String profileTextView.text = user.object(forKey: "profileSentence") as? String let file = NCMBFile.file(withName: NCMBUser.current()?.objectId, data: nil) as! NCMBFile file.getDataInBackground { (data, error) in if error != nil{ print(error) }else{ if data != nil { let image = UIImage(data: data!) self.mainImageView.image = image } } } }else{ } } var editDelegate: ProfileEditDelegate? @IBAction func saveProfile(){ let user = NCMBUser.current() user?.setObject(self.displayNameTextField.text, forKey: "userName") user?.setObject(self.searchIdTextfield.text, forKey: "searchId") user?.setObject(self.profileTextView.text, forKey: "profileSentence") editDelegate?.didEditProfile(profileText: profileTextView.text) print("ああああああああああああああああああ") user?.saveInBackground({ (error) in if error != nil { print(error) }else{ print("いいいいいいいいいいいいいいいいいい") self.dismiss(animated: true, completion: nil) } }) } @IBAction func cancel(){ self.dismiss(animated: true, completion: nil) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage let resizedImage = selectedImage.scale(byFactor: 0.1) picker.dismiss(animated: true, completion: nil) let data = resizedImage!.pngData() let file = NCMBFile.file(withName: NCMBUser.current()?.objectId, data: data) as! NCMBFile file.saveInBackground({ (error) in if error != nil{ print(error) }else{ self.mainImageView.image = resizedImage } }) { (progress) in print(progress) } } }

UserPageViewController.swift

import

1import NCMB 2import PKHUD 3 4class UserPageViewController: UIViewController, ProfileEditDelegate{ 5 func didEditProfile(profileText: String) { 6 print("ーーーーーーー呼ばれてる") 7 profileTextView.text = profileText 8 print("ーーーーーーー呼ばれてる") 9 } 10 11 12 13 @IBOutlet var mainImageView: UIImageView! 14 15 @IBOutlet var subImageCollectionView: UICollectionView! 16 @IBOutlet var nameLabel: UILabel! 17 @IBOutlet var followerButton: UIButton! 18 @IBOutlet var followingButton: UIButton! 19 @IBOutlet var profileTextView: UITextView! 20 @IBOutlet var goToEdit: UIButton! 21 22 23 24 25 26 override func viewDidLoad() { 27 super.viewDidLoad() 28 29 30 31 if let user = NCMBUser.current(){ 32 33 HUD.flash(.progress, delay: 0.1){ 34 finished in 35 DispatchQueue.main.async { 36 self.nameLabel.text = user.object(forKey: "userName") as? String 37 self.profileTextView.text = user.object(forKey: "profileSentence") as? String 38 self.navigationItem.title = user.object(forKey: "searchId") as? String 39 let file = NCMBFile.file(withName: NCMBUser.current()?.objectId, data: nil) as! NCMBFile 40 41 file.getDataInBackground { (data, error) in 42 if error != nil { 43 print(error) 44 }else{ 45 if data != nil{ 46 let image = UIImage(data: data!) 47 self.mainImageView.image = image 48 } 49 50 } 51 } 52 } 53 } 54 55 56 }else{ 57 let storyboard = UIStoryboard(name: "SignIn", bundle: Bundle.main) 58 let rootViewController = storyboard.instantiateViewController(withIdentifier: "RootNavigationController") 59 UIApplication.shared.keyWindow?.rootViewController = rootViewController 60 61 let ud = UserDefaults.standard 62 ud.set(false, forKey: "isLogin") 63 ud.synchronize() 64 } 65 } 66 67 override func viewWillAppear(_ animated: Bool) { 68 if let user = NCMBUser.current(){ 69 70 nameLabel.text = user.object(forKey: "userName") as? String 71 profileTextView.text = user.object(forKey: "profileSentence") as? String 72 navigationItem.title = user.object(forKey: "searchId") as? String 73 74 let file = NCMBFile.file(withName: NCMBUser.current()?.objectId, data: nil) as! NCMBFile 75 76 file.getDataInBackground { (data, error) in 77 if error != nil { 78 print(error) 79 }else{ 80 if data != nil{ 81 let image = UIImage(data: data!) 82 self.mainImageView.image = image 83 } 84 85 } 86 } 87 88 print(profileTextView) 89 90 91 }else{ 92 let storyboard = UIStoryboard.init(name: "SignIn", bundle: Bundle.main) 93 94 let rootViewController = storyboard.instantiateViewController(withIdentifier: "RootNavigationController") 95 UIApplication.shared.keyWindow?.rootViewController = rootViewController 96 97 let ud = UserDefaults.standard 98 ud.set(false, forKey: "isLogin") 99 ud.synchronize() 100 101 } 102 103 104 105 106 107 } 108 109 110 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 111 if segue.identifier == "fromUserPageToFollower"{ 112 let destinationcontroller = segue.destination as! FollowerViewController 113 114 destinationcontroller.passedTappedUser = NCMBUser.current() 115 } 116 117 if segue.identifier == "fromUserPageToFollowing"{ 118 let destinationcontroller = segue.destination as! FollowingViewController 119 120 destinationcontroller.passedTappedUser = NCMBUser.current() 121 } 122 } 123 124 125 126 127 128 129 130 131 132} 133

print()を使って確認してみたところ、EditProfileViewController.swiftの方は全て呼ばれるべき関数等は呼ばれていましたが、UserPageViewController.swiftの

func didEditProfile(profileText: String) { print("ーーーーーーー呼ばれてる") profileTextView.text = profileText print("ーーーーーーー呼ばれてる") }

の部分は呼ばれていることが確認できません。
また、今はとりあえずプロフィール文のみの変更をモーダルを閉じ次第反映させようとしています。よろしくお願いします。

以下の画像のようにプロフィールページから編集ページはモーダルで繋がれています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TsukubaDepot

2020/08/13 03:27

UserPageViewController.swift には同じコードが何度も現れるのですが、これはコピーミスでしょうか。 また、EditProfileViewController が呼び出されるであろう場所も見つからないのですが、これはどこで呼び出されていますでしょうか。 ところで、delegate が呼び出されない一番多くありがちな原因ですが、tableView でいえば tableView.delegate = self といった感じで移譲先のインスタンスを設定することを忘れているパターンかと思います。こちらは大丈夫でしょうか。
退会済みユーザー

退会済みユーザー

2020/08/13 04:28

お返事ありがとうございます。コピーミスでした、申し訳ありませんでした。 自分の勉強不足で移譲先のインスタンスを設定できているのかすら分からない状況です。
TsukubaDepot

2020/08/13 05:06

EditProfileViewController には、どのようにして遷移しているのでしょうか。 ボタンに直接 Segue を設定して遷移していらっしゃるのでしょうか。
退会済みユーザー

退会済みユーザー

2020/08/13 05:11

右上の青い歯車のアイコンからモーダル表示させています
guest

回答1

0

ベストアンサー

全体的な実装が見えていないのですが、概ねこんな感じになるかと思います。

動きが分かりやすくなるように、余計な機能(NMCBなど)はバッサリと削ってあります。

Swift

1import UIKit 2 3class ViewController: UIViewController, ProfileEditDelegate { 4 func didEditProfile(profileText: String) { 5 // MARK: EditViewController でセットした値を表示するだけ 6 print(profileText) 7 } 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 } 12 13 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 14 // MARK: EditViewController への Segue を選択した場合 15 if segue.identifier == "EditVCSegue" { 16 // MARK: 遷移先が Navigaton Controller の場合 17 // カスタムクラスの場合には UINavigationController を適切な名前に変更 18 if let nextNC = segue.destination as? UINavigationController { 19 if let nextVC = nextNC.viewControllers[0] as? EditProfileViewController { 20 // MARK: EditProfileViewController の editDelegate に移譲先のインスタンスをセット 21 nextVC.editDelegate = self 22 } 23 } 24 25 // MARK: 遷移先が通常の View Controller の場合はこちら 26 // if let nextVC = segue.destination as? EditProfileViewController { 27 // nextVC.editDelegate = self 28 // } 29 } 30 } 31}

ViewController では、ボタンから次の View Controller へ直接 Segue を張っているので、ボタンを押すと prepare(for:sender:)が直接呼ばれますが、performSegue(withIdentifier:sender:) でインスタンス化した場合でも基本的に同じとなります。

prepare(for:sender:) で次の View Controller のインスタンスが見えますので、そこで delegate のためのインスタンスをセットするような形になります。

おそらく、EditProfileViewController は Navigation Controller 経由となっていると思われるので上記のような実装になっていますが、もし直接 View Controller をインスタンス化しているのであれば、コメントアウトした方で大丈夫です(いわゆる値渡しと呼ばれる方法と同じです)。

Swift

1import UIKit 2 3// MARK: delegate として宣言するプロトコルは弱参照させるため class を継承させる 4protocol ProfileEditDelegate: class { 5 func didEditProfile(profileText: String) 6} 7 8class EditProfileViewController: UIViewController { 9 // MARK: weak キーワードを使って弱参照させる 10 weak var editDelegate: ProfileEditDelegate? 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 } 15 16 @IBAction func saveProfile(){ 17 editDelegate?.didEditProfile(profileText: "Saveボタンがタップされた。") 18 self.dismiss(animated: true, completion: nil) 19 } 20 21 @IBAction func cancel(){ 22 self.dismiss(animated: true, completion: nil) 23 } 24}

遷移先ですが、まず delegate として宣言するプロトコルは弱参照させる必要があるため、class を継承するようにします。

また、editDelegateweak キーワードを付けることで弱参照させます。プロトコルが class を継承していなければ weak キーワードをつけることができずエラーとなりますのでご注意ください。

あとは、基本的にオリジナルのままで大丈夫かと思います。

投稿2020/08/13 07:07

TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/08/14 01:13

返信遅れて申し訳ありません、無事機能しました。もっと勉強します。
退会済みユーザー

退会済みユーザー

2020/08/14 01:13

ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問