teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

実装例を提示

2020/03/11 13:49

投稿

thyda.eiqau
thyda.eiqau

スコア2982

answer CHANGED
@@ -3,4 +3,120 @@
3
3
 
4
4
  同じ現象ではありませんが関連するteratailの質問とStackoverflowを貼っておきます。こちらは、表示が真っ白になったり遷移しなかったりという内容です。
5
5
  - [iOS - swift WKWebViewで表示したブラウザのpdfファイルを開きたい|teratail](https://teratail.com/questions/209048)
6
- - [iOS 13 WKWebView not showing pdf file anymore](https://stackoverflow.com/questions/58073513/ios-13-wkwebview-not-showing-pdf-file-anymore)
6
+ - [iOS 13 WKWebView not showing pdf file anymore](https://stackoverflow.com/questions/58073513/ios-13-wkwebview-not-showing-pdf-file-anymore)
7
+
8
+ ----
9
+ Mar 11, 2020 追記
10
+ 仕様固めに時間がかかってしまいました。
11
+ 「いったんWebコンテンツを開くが、PDFのダウンロードリンクを開く場合がある」というシチュエーションで、当方では下記のように実装しました。ご参考になれば幸いです。
12
+ ```objectivec
13
+ // MyWebViewController.h
14
+ #import <UIKit/UIKit.h>
15
+ #import <WebKit/WebKit.h>
16
+ #import <QuickLook/QuickLook.h>
17
+
18
+ NS_ASSUME_NONNULL_BEGIN
19
+
20
+ @interface MyWebViewController : UIViewController <WKNavigationDelegate, WKUIDelegate, QLPreviewControllerDataSource>
21
+
22
+ @property (nonatomic) NSString *firstUrl;
23
+
24
+ @end
25
+
26
+ NS_ASSUME_NONNULL_END
27
+ ```
28
+
29
+ ```objectivec
30
+ // MyWebViewController.m
31
+
32
+ @interface MyWebViewController()
33
+
34
+ @property (nonatomic) WKWebView *webView;
35
+ @property (nonatomic) NSString *previewFilePath;
36
+
37
+ @end
38
+
39
+ - (void)viewDidLoad {
40
+ [super viewDidLoad];
41
+ self.webView = [[WKWebView alloc] init];
42
+ self.webView.navigationDelegate = self;
43
+ self.webView.UIDelegate = self;
44
+ self.webView.translatesAutoresizingMaskIntoConstraints = false;
45
+
46
+ [self.view addSubview:self.webView];
47
+ // 制約の設定等は省略...
48
+ }
49
+
50
+ - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
51
+ NSURL *url = navigationAction.request.URL;
52
+ if([url.absoluteString compare:self.firstUrl] == NSOrderdSame) {
53
+ decisionHandler(WKNavigationActionPolicyAllow);
54
+ return;
55
+ }
56
+
57
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
58
+ [[NSURLSession.sharedSession dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
59
+ if(error != nil || data == nil || data.length == 0) {
60
+ NSString *errorDescription = [@"ファイルのダウンロードに失敗しました。" stringByAppendingString:error.localizedDescription];
61
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"通信エラー" message:errorDescription preferredStyle:UIAlertControllerStyleAlert];
62
+ [alertController addAction:[UIAlertAction actionWithTitle:@"閉じる" style:UIAlertActionStyleDefault handler:nil]];
63
+ dispatch_async(dispatch_get_main_queue(),^{
64
+ [self presentViewController:alertController animated:YES completion:nil];
65
+ });
66
+ decisionHandler(WKNavigationActionPolicyCancel);
67
+ return;
68
+ }
69
+
70
+ // PDF以外はとりあえず通すが何が起こっても知らない
71
+ NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
72
+ if([res.allHeaderFields[@"Content-Type"] compare:@"application/pdf"] != NSOrderedSame) {
73
+ decisionHandler(WKNavigationActionPolicyAllow);
74
+ return;
75
+ }
76
+
77
+ NSString * __block filename = @"ダウンロードファイル";
78
+ [[(NSString*)res.allHeaderFields[@"Content-Disposition"] componentsSeparatedByString:@";"] enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
79
+ NSArray<NSString*> *pair = [[obj stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsSeparatedByString:@"="];
80
+ if([pair[0] compare:@"filename"] != NSOrderedSame) return;
81
+ filename = [pair[1] stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
82
+ if([filename hasPrefix:@"\""]) filename = [filename substringFromIndex:1];
83
+ if([filename hasSuffix:@"\""]) filename = [filename substringToIndex:filename.length - 1];
84
+ }];
85
+
86
+ NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/"] stringByAppendingPathComponent:filename];
87
+ [data writeToFile:filePath atomically:YES];
88
+ self.previewFilePath = filePath;
89
+
90
+ dispatch_async(dispatch_get_main_queue(),^{
91
+ MyQuickLookViewController* ql = [[MyQuickLookViewController alloc] init];
92
+ [self.navigationController pushViewController:ql animated:YES];
93
+ ql.dataSource = self;
94
+ [ql refreshCurrentPreviewItem];
95
+ });
96
+
97
+ decisionHandler(WKNavigationActionPolicyCancel);
98
+ }] resume];
99
+ });
100
+ }
101
+
102
+ // MARK: - QuickLook
103
+ - (void)presentQuickLookPreviewController {
104
+ dispatch_async(dispatch_get_main_queue(),^{
105
+ MyQuickLookViewController* ql = [[MyQuickLookViewController alloc] init];
106
+ [self.navigationController pushViewController:ql animated:YES];
107
+ ql.dataSource = self;
108
+ [ql refreshCurrentPreviewItem];
109
+ });
110
+ }
111
+
112
+ // MARK: QLPreviewControllerDataSource
113
+ - (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController*)previewController {
114
+ return 1;
115
+ }
116
+
117
+ /// プレビューするファイルのパスを NSURL で返す
118
+ - (id<QLPreviewItem>)previewController:(QLPreviewController*)controller previewItemAtIndex:(NSInteger)index {
119
+ NSURL *url = [NSURL fileURLWithPath:self.previewFilePath];
120
+ return url;
121
+ }
122
+ ```