## やりたいこと
別ファイルのテキストデータを参照したいです。
## 試したこと
guard let
は関数内でないと使えず、static let
群を関数外にするとスコープから外れて定数repo
を参照出来ないので、
関数を作ってまとめて入れたら、
参照先(元?)のProfileDetailVC
から参照出来なくなりました..当然なのですが...????
swift
1// Constants.swift 2import UIKit 3 4var selectedUser: SearchRootVC? 5 6struct RepoTxt { 7 8 func Sample() { 9 guard let selectedUser = selectedUser else { return } 10 let repo = selectedUser.repo[selectedUser.repoToPass] 11 12 let title = repo[ApiKey.userName] as? String 13 let language = "Written in (repo["language"] as? String ?? "")" 14 let stars = "(repo["stargazers_count"] as? Int ?? 0) stars" 15 let watchers = "(repo["wachers_count"] as? Int ?? 0) watchers" 16 let forks = "(repo["forks_count"] as? Int ?? 0) forks" 17 let issues = "(repo["open_issues_count"] as? Int ?? 0) open issues" 18 19 } 20 21}
swift
1// ProfileDetailVC 2// ここからテキストデータを参照したい。 3 func setupUI() { 4 TitleLbl.text = RepoTxt.title // Type 'RepoTxt' has no member 'title' 5 LanguageLbl.text = RepoTxt.language // Type 'RepoTxt' has no member 'language' 6 StarsLbl.text = RepoTxt.stars //以下同様 7 WatchersLbl.text = RepoTxt.watchers 8 ForksLbl.text = RepoTxt.forks 9 IssuesLbl.text = RepoTxt.issues 10 }
## コード
一応、selectedUser
のデータ型であるSearchRootVC
も添付しておきます。
swift
1import UIKit 2 3class SearchRootVC: UITableViewController, UISearchBarDelegate { 4 5 @IBOutlet weak var searchBar: UISearchBar! 6 7 var repoToPass: Int = 0 8 9 var task: URLSessionTask? 10 var repo: [[String: Any]] = [] 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 setupTableView() 15 tableViewBgImage() 16 } 17 18 // 以下3つ、元から用意されているsearchBar関数名なので、変更NG。 19 func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool { 20 searchBar.text = "" 21 searchBar.autocapitalizationType = .none // 検索時、先頭を小文字で始める 22 return true 23 } 24 25 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 26 task?.cancel() 27 } 28 29 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 30 // キーボード非表示 31 searchBar.resignFirstResponder() 32 33 // MARK: - 不用意なIUOを削除。 34 // let query = searchBar.text! 35 guard let query = searchBar.text, query.isEmpty == false else { 36 print("検索文字がない") 37 return 38 } 39 40 // word, completion, errorHandler 3つの引数をメソッドに渡す。 41 task = SearchAPI.getRandomRepoUrlSession(query, completionHandler: { items in 42 self.repo = items 43 DispatchQueue.main.async { 44 // UIを更新する処理 45 self.tableView.reloadData() 46 } 47 }, errorHandler: { error in 48 // オプショナルチェイニング 49 debugPrint(error?.localizedDescription ?? "") 50 }) 51 } 52 53 // MARK: - オプショナルチェイニング 54 // 値があるとアンラップ。但し、それに続くプロパティやメソッドの戻り値は「オプショナル型」になる。(-> nilの場合 nil を返すため) 55 // nilの場合 nil を返す。それに続く処理をすべてキャンセル (-> なので安全) 56 57 // MARK: - ?? 58 // 「??」... nil結合演算子 (nil-coalescing) 59 // A ?? B ... Aに値があるとAをアンラップ。Aが nil だとBを返す。 60 61 func setupTableView() { 62 // delegateは、delegatorに処理を委譲された側 63 searchBar.delegate = self 64 } 65 66 // MARK: - TableView で背景画像を表示 67 func tableViewBgImage() { 68 let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.tableView.frame.width, height: self.tableView.frame.height)) 69 let image = UIImage(named: "bg_right1") 70 71 imageView.image = image 72 imageView.alpha = 0.8 73 74 self.tableView.backgroundView = imageView 75 } 76 77 // MARK: - // Segueが実行される前に呼び出される 78 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 79 // Segueの識別子確認 80 if segue.identifier == Segues.toProfileDetail { 81 // 遷移先ViewCntrollerの取得 82 if let detailVC = segue.destination as? ProfileDetailVC { 83 // 値の設定 84 detailVC.selectedUser = self 85 } 86 } 87 } 88} 89 90 91// extension 92 93extension SearchRootVC { 94 95 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 96 return repo.count 97 } 98 99 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 100 101 // dequeueReusableCellで、セルを再利用。 102 // nilを返さない為、オプショナルバインディングは不要。 103 104 // MARK: - セルの再利用 105 let cell = tableView.dequeueReusableCell(withIdentifier: "RepositoryCell", for: indexPath) 106 107 let userRepo = repo[indexPath.row] 108 109 // MARK: - nil回避しつつ、nilの場合は「--None--」を表示 110 if let userName = userRepo[ApiKey.userName] as? String { 111 cell.textLabel?.text = userName 112 } else { 113 cell.textLabel?.text = "--None--" 114 } 115 // カスタムクラスの参照を修正。(-> detailTextLabelの表示) 116 if let language = userRepo[ApiKey.language] as? String { 117 cell.detailTextLabel?.text = language 118 } else { 119 cell.detailTextLabel?.text = "--None--" 120 } 121 122 return cell 123 } 124 125 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 126 repoToPass = indexPath.row 127 performSegue(withIdentifier: Segues.toProfileDetail, sender: self) 128 } 129} 130 131// MARK: - Cellの備考 (registerとは?) 132// register() ... 用意したviewをcellのテンプレートとして登録するメソッドであり、cellの再利用に必要。 133// Right Detail を表示は、コード不可 StoryBoard可なので、register()は使用しない。 134 135// MARK: - クラスメソッドとして定義 136class SearchAPI { 137 // staticとして宣言すると、クラスのインスタンス化が不要。 138 static func getRandomRepoUrlSession(_ query: String, completionHandler completion: @escaping ([[String: Any]]) -> (), errorHandler: @escaping (Error?) -> ()) -> URLSessionTask? { 139 140 // MARK: - 下記の部分はメソッドに渡す前に処理しておく 141 // let word = searchBar.text! 142 // guard let word = searchBar.text, word.isEmpty == false else { 143 // print("検索文字がない") 144 // return 145 // } 146 147 let repositoryUrl = githubBaseUrl + query 148 149 guard let url = URL(string: repositoryUrl) else { return nil } 150 151 let task = URLSession.shared.dataTask(with: url) { (data, responce, error) in 152 153 guard error == nil else { 154 // MARK: - 処理をクロージャに任せる 155 errorHandler(error) 156 return 157 } 158 159 guard let data = data else { return } 160 161 // try!は、例外が発生したときにはクラッシュするので修正。(-> エラーが起こり得ないケースでのみ使用可) 162 // try?で例外を安全に無視できるが、エラーを表示するため do-catch を使用。 163 164 do { 165 let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] 166 if let items = json?["items"] as? [[String: Any]] { 167 // MARK: - 処理をクロージャに任せる 168 completion(items) 169 // MARK: - 以下の処理はクロージャに任せる 170 // self.repo = items 171 // // DispatchQueue で一つ以上のタスクを管理し、async で複数のAPIの非同期通信を実行。 172 // DispatchQueue.main.async { 173 // // UIを更新する処理 174 // self.tableView.reloadData() 175 // } 176 } 177 } catch { 178 // MARK: - 処理をクロージャに任せる 179 errorHandler(error) 180 } 181 } 182 task.resume() 183 184 return task 185 } 186}
質問は以上です。
お時間あるときに、ご返信頂けましたら幸いです????
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。