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

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

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

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

Q&A

解決済

1回答

417閲覧

TableViewよりSFSafariViewControllerに遷移して複数のURLを渡して表示させる方法

Tomzy

総合スコア104

Swift

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

0グッド

0クリップ

投稿2018/04/06 10:00

行いたいこと

下記のTableView第1画面よりセルをタップして第2画面のSafari画面に遷移すること目論んでいます。
TableView第1画面
イメージ説明
第2画面のSafari画面
イメージ説明

注:この画像はあとからSafariを表示してスクリーンショットを撮ったものです。コードで表示された画面には左上に完了ボタンが表示されましたが、ボタンを押してもSafariから抜けることはできませんでした。

行ったこと

1個のURLを DetailTomzyViewController.swift上にコーディングして、第1画面のセルをタップしてSafari画面に遷移し、ひとつのURLを表示させることは成功しました。

しかし、 ViewTomzyControllerJp.swift上に下記のコードのごとく6個のURLをアレイで記載して第1画面のセルをタップしてSafari画面に遷移し、6個のURLを表示させることができていません。

それぞれのファイル上のコードは下記のとおりです。エラー表示も下記に記載します。

ViewTomzyControllerJp.swiftのコード

// VoiceAsisst01Free // // Created by Tomiji Suzuki on H30/04/03. // Copyright © 平成30年 Tomiji Suzuki. All rights reserved. // import Foundation import UIKit import WebKit class ViewTomzyControllerJp: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet var table:UITableView! // section毎の画像配列 let imgArray: NSArray = ["Video_r.png","Video_r.png","Book_g.png","Book_g.png","Book_g.png","Book_g.png"] let label1Array: NSArray = ["操作方法(動画)","ゲームの遊び方(動画)","このアプリについて","Q & A","トミ爺アプリについて","開発者について"] let textsURL = ["http://tomzyapp.com/voiceinput02/01.html", "http://tomzyapp.com/voiceinput02/02.html", "http://tomzyapp.com/voiceinput02/03.html", "http://tomzyapp.com/voiceinput02/04.html", "http://tomzyapp.com/voiceinput02/05.html", "http://tomzyapp.com/voiceinput02/06.html"] var selectedIndexPath: IndexPath! override func viewDidLoad() { super.viewDidLoad() } //Table Viewのセルの数を指定 func tableView(_ table: UITableView, numberOfRowsInSection section: Int) -> Int { print ("Tomzy01セルの数を指定") return imgArray.count } //各セルの要素を設定する func tableView(_ table: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // tableCell の ID で UITableViewCell のインスタンスを生成 let cell = table.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) let img = UIImage(named: imgArray[indexPath.row] as! String) // Tag番号 1 で UIImageView インスタンスの生成 let imageView = cell.viewWithTag(1) as! UIImageView imageView.image = img // Tag番号 2 で UILabel インスタンスの生成 let label1 = cell.viewWithTag(2) as! UILabel label1.text = String(describing: label1Array[indexPath.row]) print ("Tomzy02セルの要素を設定") return cell } // Cell の高さを120にする func tableView(_ table: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat { print ("Tomzy03セルの高さを指定") return 70.0 } //////上記のTableViewの表示は成功している/////// //ここから後は第2画面に遷移してウェブサイトSafariを表示する //テーブルビューのセルがタップされた処理 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print ("Tomzy04タップセルが選択された") selectedIndexPath = indexPath //cellが選択された場合 //toDetailViewへ遷移するためにsegueを呼び出す performSegue(withIdentifier: "toDetailView", sender: self) print ("Tomzy05セルがタップされた") } override func prepare(for segue: UIStoryboardSegue, sender: Any!) { if (segue.identifier == "toDetailView") { let subVC = (segue.destination as? DetailTomzyViewController)! // print ("Tomzy06画面が遷移した") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }

DetailTomzyViewController.swift上のコード

// VoiceAsisst01Free // // Created by Tomiji Suzuki on H30/03/21. // Copyright © 平成30年 Tomiji Suzuki. All rights reserved. // import Foundation import UIKit import SafariServices class DetailTomzyViewController: UIViewController { var urlString : String? override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { //渡されたURLをWebViewにリクエストする let url = URL(string: urlString!) let request = URLRequest(url: url!) let safariVC = SFSafariViewController(url: NSURL(string: request)! as URL) present(safariVC, animated: true, completion: nil) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func safariViewControllerDidFinish(controller: SFSafariViewController) { print("close") } }

エラー表示

Cannot convert value of type 'URLRequest' to expected argument type 'String'

エラーの位置

イメージ説明

教えて頂きたいとこ(2件)

1.上記エラーを解消してSafari画面に遷移し、6個のURLを表示させるコードを教えてください。
2.第2画面のSafariが表示されたあと、完了ボタンを押したとき、元のアプリに戻るコードは

func safariViewControllerDidFinish(controller: SFSafariViewController) {

であると見つけたのですが、第1画面に戻るコードはどのように書いたらよいでしょうか。

ご参考事項:

環境は下記のとおりです。
MacBook Pro (15-inch, 2016)
High Sierra OS10.13.2
Version 9.2 (9C40b)Swift4にバージョンアップしました。
「音声入力アシスト」は既に2017.12にリリースできましたが、現在機能を充実し、更に英語を標準として日本語をローカリゼーションしている最中です。よろしくお願いします。
なお、SFSafariViewControllerに関連して
リンク内容[https://i-app-tec.com/ios/web-browser.html#2]

を参照しました。

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

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

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

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

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

newmt

2018/04/06 22:34

DetailTomzyViewControllerのurlStringへはどこで値を設定していますでしょうか?
guest

回答1

0

ベストアンサー

以下を試してみるといかがでしょうか?

// ViewTomzyControllerJp // override func prepare(for segue: UIStoryboardSegue, sender: Any!)の中 // 表示したいURLをDetailTomzyViewControllerに渡す let subVC = (segue.destination as? DetailTomzyViewController)! let textURL = textsURL[selectedIndexPath.row] subVC.urlString = textURL
// DetailTomzyViewController // override func viewDidAppear(_ animated: Bool)の中 // SFSafariViewControllerにURLを設定する let url = URL(string: urlString!) let safariVC = SFSafariViewController(url: url)
// 前の画面に戻る func safariViewControllerDidFinish(controller: SFSafariViewController) { self.dismiss(animated: true, completion: nil) }

参考記事:
https://qiita.com/okuderap/items/3bd2fa0cb508cbd00ffd
http://appleharikyu.jp/iphone/?p=1074

【追記】

// SFSafariViewControllerDelegateを追加 class ViewTomzyControllerJp: UIViewController, UITableViewDataSource, UITableViewDelegate, SFSafariViewControllerDelegate {
// didSelectRowAtを変更 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print ("Tomzy04タップセルが選択された") let textUrl = textsURL[indexPath.row] let url = URL(string: textUrl) let safariVC = SFSafariViewController(url: url!) safariVC.delegate = self present(safariVC, animated: true, completion: nil) }
// ViewTomzyControllerJpに追加 func safariViewControllerDidFinish(_ controller: SFSafariViewController) { print("close") controller.dismiss(animated: true) }

投稿2018/04/06 22:46

編集2018/04/07 02:27
newmt

総合スコア1277

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

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

Tomzy

2018/04/06 23:47

ありがとうございました。 Xcodeに導かれながら1字づつインプットしていきました。 インプットが終わったあと // 表示したいURLをDetailTomzyViewControllerに渡す subVC.urlString = textURLのところに Cannot assign value of type '[Int]' to type 'String?' というエラーがでたので考えているところです。
newmt

2018/04/07 00:03

textURLの型は何になっていますでしょうか?
Tomzy

2018/04/07 00:52

String型です。
Tomzy

2018/04/07 01:20

Int型をString型に変換するコードを加えましたらエラーは消えましたが、ビルド後第2画面が表示するに至っていません。 override func prepare(for segue: UIStoryboardSegue, sender: Any!) { if (segue.identifier == "toDetailView") { // 表示したいURLをDetailTomzyViewControllerに渡す let subVC = (segue.destination as? DetailTomzyViewController)! let textURL = [selectedIndexPath.row] //subVC.urlString = textURL let strtextURL = String(describing: textURL) //var strB = intA.description subVC.urlString = strtextURL print ("Tomzy06画面が遷移した") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
newmt

2018/04/07 01:27 編集

一箇所異なっている所があります。 let textURL = [selectedIndexPath.row] ↓ let textURL = textsURL[selectedIndexPath.row] 私の環境ですと画面遷移しますね。デバックした際にoverride func prepareは呼ばれていますでしょうか?
Tomzy

2018/04/07 01:26

第1画面は表示されます。そのひとつのセルをタップすると第2画面に遷移する筈ですが、止まります。タブコメントは下記のとおりです。 接続など精査します。 Tomzy04タップセルが選択された 2018-04-07 10:15:53.902556+0900 VoiceAsisst01Free[15587:1514646] Unknown class DetailTomzyViewController in Interface Builder file. Could not cast value of type 'UIViewController' (0x107906ca8) to 'VoiceAsisst01Free.DetailTomzyViewController' (0x1015375d0). 2018-04-07 10:15:53.903121+0900 VoiceAsisst01Free[15587:1514646] Could not cast value of type 'UIViewController' (0x107906ca8) to 'VoiceAsisst01Free.DetailTomzyViewController' (0x1015375d0).
newmt

2018/04/07 01:28

storyboardの第2画面のViewControllerにDetailTomzyViewControllerは設定されていますでしょうか?
Tomzy

2018/04/07 01:32

下記のように修正しましたが let subVC = (segue.destination as? DetailTomzyViewController)! のところにThread 1: signal SIGABRTがでました。 override func prepare(for segue: UIStoryboardSegue, sender: Any!) { if (segue.identifier == "toDetailView") { // 表示したいURLをDetailTomzyViewControllerに渡す let subVC = (segue.destination as? DetailTomzyViewController)! //let textURL = [selectedIndexPath.row] let textURL = textsURL[selectedIndexPath.row] //subVC.urlString = textURL let strtextURL = String(describing: textURL) //var strB = intA.description subVC.urlString = strtextURL print ("Tomzy06画面が遷移した") } }
Tomzy

2018/04/07 01:36

成功しました。 ClassにはDetailTomzyViewControllerを選んでありましたが、ModuleのところがnonになっていましたのでVoiceAsisst01Freeを選択して再度ビルドしたら成功でした。ありがとうございました。
newmt

2018/04/07 01:37

解決できてよかったです。
Tomzy

2018/04/07 01:38

整理して成功したコードを次のコメントに記入します。
Tomzy

2018/04/07 01:43

第1画面のコード  ↓ ↓ ↓ // ViewTomzyControllerJp.swift // VoiceAsisst01Free // // Created by Tomiji Suzuki on H30/04/03. // Copyright © 平成30年 Tomiji Suzuki. All rights reserved. // import Foundation import UIKit import WebKit class ViewTomzyControllerJp: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet var table:UITableView! // section毎の画像配列 let imgArray: NSArray = ["Video_r.png","Video_r.png","Book_g.png","Book_g.png","Book_g.png","Book_g.png"] let label1Array: NSArray = ["操作方法(動画)","ゲームの遊び方(動画)","このアプリについて","Q & A","トミ爺アプリについて","開発者について"] let textsURL = ["http://tomzyapp.com/voiceinput02/01.html", "http://tomzyapp.com/voiceinput02/02.html", "http://tomzyapp.com/voiceinput02/03.html", "http://tomzyapp.com/voiceinput02/04.html", "http://tomzyapp.com/voiceinput02/05.html", "http://tomzyapp.com/voiceinput02/06.html"] var selectedIndexPath: IndexPath! override func viewDidLoad() { super.viewDidLoad() } //Table Viewのセルの数を指定 func tableView(_ table: UITableView, numberOfRowsInSection section: Int) -> Int { print ("Tomzy01セルの数を指定") return imgArray.count } //各セルの要素を設定する func tableView(_ table: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // tableCell の ID で UITableViewCell のインスタンスを生成 let cell = table.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) let img = UIImage(named: imgArray[indexPath.row] as! String) // Tag番号 1 で UIImageView インスタンスの生成 let imageView = cell.viewWithTag(1) as! UIImageView imageView.image = img // Tag番号 2 で UILabel インスタンスの生成 let label1 = cell.viewWithTag(2) as! UILabel label1.text = String(describing: label1Array[indexPath.row]) print ("Tomzy02セルの要素を設定") return cell } // Cell の高さを120にする func tableView(_ table: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat { print ("Tomzy03セルの高さを指定") return 70.0 } //////上記のTableViewの表示は成功している/////// //ここから後は第3画面に遷移してウェブサイトを表示する //テーブルビューのセルがタップされた処理 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print ("Tomzy04タップセルが選択された") selectedIndexPath = indexPath //cellが選択された場合 //toDetailViewへ遷移するためにsegueを呼び出す performSegue(withIdentifier: "toDetailView", sender: self) print ("Tomzy05セルがタップされた") } override func prepare(for segue: UIStoryboardSegue, sender: Any!) { if (segue.identifier == "toDetailView") { // 表示したいURLをDetailTomzyViewControllerに渡す let subVC = (segue.destination as? DetailTomzyViewController)! //let textURL = [selectedIndexPath.row] let textURL = textsURL[selectedIndexPath.row] //textURLはInt型なのでString型に変換 let strtextURL = String(describing: textURL) subVC.urlString = strtextURL print ("Tomzy06画面が遷移した") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
Tomzy

2018/04/07 01:53

newtさんへ ありがとうございました。 第2画面にSafariが表示されましたが、左上の完了ボタンをタップしても、一旦画面が白くなるだけでサファリ画面に戻ってしまいます。下記のコードを override func didReceiveMemoryWarning() { の後に書いてあったのを前に移しても結果変わりませんでした。このサファリからの脱出方法を教えてください。 //サファリより元の画面に戻るコード func safariViewControllerDidFinish(controller: SFSafariViewController) { print("close") self.dismiss(animated: true, completion: nil) }
newmt

2018/04/07 02:28

すいません。segueで画面遷移をするとうまくいかないようです。回答に追記した方法で実現できるのですが、要件に合いますでしょうか?(DetailTomzyViewControllerは使いません)
Tomzy

2018/04/07 03:01

レスポンスありがとうございました。DetailTomzyViewControllerの方に書いていました。ViewTomzyControllerJpに書き直したのですが、Use of undeclared type SFSafariViewController'というエラーがでたりしていますので、じっくり落ち着いて考えてみます。ありがとうございました。
newmt

2018/04/07 03:03

すいません一つ書き忘れていました。 import SafariServices を追加してみてください。
Tomzy

2018/04/07 05:49

import SafariServices を入れましたらエラーは消えました。しかし、変わりません。第2画面にSafariが表示されましたが、左上の完了ボタンをタップしても、一旦画面が白くなるだけでサファリ画面に戻ってしまいます。
Tomzy

2018/04/07 05:56

念のため関係部分のコードを下に掲載します。 var urlString : String? //ここから後は第3画面に遷移してウェブサイトを表示する //テーブルビューのセルがタップされた処理 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print ("Tomzy04タップセルが選択された") selectedIndexPath = indexPath //cellが選択された場合 //toDetailViewへ遷移するためにsegueを呼び出す performSegue(withIdentifier: "toDetailView", sender: self) print ("Tomzy05セルがタップされた") } override func prepare(for segue: UIStoryboardSegue, sender: Any!) { if (segue.identifier == "toDetailView") { // 表示したいURLをDetailTomzyViewControllerに渡す let subVC = (segue.destination as? DetailTomzyViewController)! //let textURL = [selectedIndexPath.row] let textURL = textsURL[selectedIndexPath.row] //textURLはInt型なのでString型に変換 let strtextURL = String(describing: textURL) subVC.urlString = strtextURL print ("Tomzy06画面が遷移した") } } //サファリより元の画面に戻るコード func safariViewControllerDidFinish(controller: SFSafariViewController) { print("close") self.dismiss(animated: true, completion: nil) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
Tomzy

2018/04/07 05:57

シミュレーターでも実機でも同じです。」
Tomzy

2018/04/07 05:59

問題が2件になってしまったので、新しい質問に整理して書きます。
newmt

2018/04/07 06:06

didSelectRowAtの部分が変わっていません。また別のご質問の方で回答します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問