ラベル UIWebView の投稿を表示しています。 すべての投稿を表示
ラベル UIWebView の投稿を表示しています。 すべての投稿を表示

2014年9月26日金曜日

iOS8のバグもしくは動作違い(随時更新)

iOS8で挙動がおかしくなった処理を書いておく。今のところ、多くは回避コードは見つかってない。

(1)UIWebViewでローカル=リソース内のHTMLファイルもしくはPDFを表示している中から外部へのリンクをクリックすると、処理から帰ってこない
ローカルからローカル、外部から外部は大丈夫みたい。

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    return YES;    // 常に内部で開く・・・リンクをクリックするとそこで処理が止まる
}
->Xcode6のバグへ移動

(2) MFMailComposeViewControllerでメイラーを表示すると、一瞬表示されるが、数秒で勝手にキャンセルがかかってしまう。
    mail=[[MFMailComposeViewController alloc]init];
    mail.mailComposeDelegate=self;
    [mail setSubject:@"title"];
    [mail setMessageBody:@"message" isHTML:NO];
    [self presentViewController:mail animated:YES completion:nil];

以下のように書いているときは、閉じてしまう。 仮に閉じなかったとして、メイルは使える状態にはならない。

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    [controller dismissViewControllerAnimated:YES completion:NULL];
    controller=nil;
}

拙作ではぷろぐらま〜ず電卓がe-Mailが使えない状態になっている。
Zeroレコーダーは開発中に気がついたので、iOS8上ではe-Mailを使えないようにした。
シミュレータ上だけの問題みたい。iOS8.0.2の実機では、開く前に警告が出ているが送信はできる。

どちらもiOS7では全く問題ないのでiOS8のバグの可能性が高い。


(3)UIWebViewのデフォルト背景色が黒に変わった
これは多分設定でなんとかなるかと。やってないけど。


(4)iPadで、ActionSheetのデリゲートの中からAirPrintのポップオーバーが表示されない

iPhoneでは問題ない。
回避策は、UIActionSheetではなく、iOS8で追加されたUIAlertControllerを使うこと。

ActionSheetから表示しようとすると、Warning: Attempt to present <UINavigationController: 0x????????>  on <表示しようとしているViewController: 0x????????> which is already presenting (null)
という警告が出て表示されない。全然わからなくて困っていたが、色々と表示条件を変えているうちにメッセージが変わり、上記のことがわかった。インターネットで調べても、stackoverflowを含めて見つからなかったので、世界初かも(^_^;)

UIAlertControllerはiOS8にはないので、バージョンを調べて処理を分ける必要がある。
また、iPhoneではUIActionSheetのままでも動くが、当然UIAlertControllerでも動く。

UIAlertControllerをiPadで使う場合は.popoverPresentationController.sourceViewと
.popoverPresentationController.batButtonItemまたは.sourceRectの設定が必須なので要注意。

メイラーの件はUIAlertControllerを使っても解決しない。

(5)WKWebViewでPDF内リンクが処理されない
PDF内にリンクがあった場合、UIWebViewではリンクが処理されるが、WKWebViewではタップが完全に無視される。回避策はない。リンク付きPDFを処理したいなら、現状WKWebViewは使えない。PDFの内部構造を解析してリンク情報を取り出し、別途ボタンを作って飛ばすとかは出来るんだけど、面倒。

(6)Tabbarでその他に入ったものから開いたViewControllerがTableViewを含む場合、
ステータスバーの部分をタップしても先頭までスクロールしない。
iOS7.1では発生、以前からそうなのかは不明。iOS8.1では修正されている。あっ、これはiOS8のバグじゃないね。

(7)NSAttributedStringでNSLinkAttributeNameを使った場合、下線が出ないことがある。出ない時はNSUnderlineStyleAttributeNameをつけても無視される。
出ることもある。truncateがあるときは表示されない。iOS7では問題ない。

2013年5月25日土曜日

UIWebViewの特異的レンダリングについて

UIWebViewはHTMLをレンダリングしてくれるが、どうも他のブラウザとは結果が異なる部分が存在する。それもHTML5とか新しい部分ではなく、極めて簡単と思われる部分で。
気がついたのは以下の部分。

(1)<pre>中の<table>内の<br>の挙動

<pre>
<table>
<tr><td>メッセージ<br>
改行</td></tr>
</table>
</pre>

と記述した場合、UIWebViewは

メッセージ

改行

となり、Chrome/Firefox/Safariでは

メッセージ
改行

となり、<br>改行の挙動が異なる。

この違いがレンダリングエンジンの違いから来るならまだ理解できるのだが、同じWebKitのはずのSafariとUIWebViewが異なるのがわけのわからんところ。UIWebViewはWebKitではないのか?

そもそも<pre>内に<table>を記述するのが文法違反だという話もあるが、現実に存在する以上、合わせて欲しい気はする。

(2)オーディオファイルのaiffが再生できない
(3)<audio>〜</audio>の部分に改行が入ってしまう
このため、<audio>定義は表示上影響の少ない部分にまとめておく必要がある。

2011年12月5日月曜日

Webページの表示仕方

WebページはUIWebViewで簡単に表示できるが、その中に画像の貼り付けなどがある場合、
その参照を解決する指定が必要になる。

クラスはこんな感じ。外部のURLへのリンクを貼る場合は、その確認のためUIAlertViewを表示する必要があるため、UIAlertViewDelegateも必要となる。

@interface HTMLViewController : UIViewController
<
UIWebViewDelegate,UIAlertViewDelegate
>
{
    IBOutlet    UIWebView *webView;
    NSURL       *url;
    UIAlertView *aview;
    BOOL        fopenAlert;
}
@property (nonatomic, retain) UIAlertView *aview;
ここではwebViewを含むnibを別途読み込んでいる。
(だからIBOutletがある。)

nib上でwebViewに以下の属性をチェックしておく。
Scaling Scales Page Fit
Detection Links
HTMLの読み込みはviewDidLoadで行う。

NSString *path=[[NSBundle mainBundle]pathForResource:@"HTMLファイル名" ofType:@"html"]; // リソース内のパスを得る
    NSString *html=[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
    NSURL *base=[NSURL fileURLWithPath:path]; // HTML内の画像のリンクを解決するため、これが非常に重要

表示
[webView loadHTMLString:html baseURL:base];
読み込んでからの設定が必要
webView.delegate=self;
    aview.delegate  =self; // 念のため
    url=nil;

    aview=[[UIAlertView alloc]initWithTitle:@"リンク"
                                    message:@"サポートページを開きますか?"
                                   delegate:self
                          cancelButtonTitle:@"いいえ"
                          otherButtonTitles:@"はい",nil];
    //
    fopenAlert=NO; // アラートを表示していないフラグ
    ~

HTML内のリンク(a href=)はそのままではwebView内で開いてしまうので、
内部のリンクはそのまま、外部へのリンクはSafariブラウザが開くように処理を差し替える。
そのため、webViewからのデリゲートを使う。

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    switch (navigationType) {
        case UIWebViewNavigationTypeLinkClicked: // リンクがクリックされたとき
            { // switch内でローカル変数を作るときはスコープ宣言が必須
            NSURL *url0=[request URL];
            if ([[url0 scheme]hasPrefix:@"file"]) {
                break; // file:の時は内部なので、何もしないで開けば良い
            }
           
            // 外部へのリンクの時は、飛ぶ前にUIAlertViewで確認する
            // 確認なしで飛ぶアプリも多いが、アップルの仕様書中では「確認せよ」と書いてある。
 
            url = [url0 copy]; // copyしないと消えてしまうので要注意
            } // ローカルスコープ
            [aview show]; // 表示したらすぐ終わる
            fopenAlert=YES; // アラートを表示しているフラグ
            return(FALSE);
        defalt:
            break;
    }
    return(TRUE);
}
urlをcopy属性で保存しているのは、アラートビューは独立して実行されるからである。

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
// アラートビューでボタンがクリックされた時に呼び出されるデリゲート
{
    NSLog(@"button=%d",buttonIndex);
    if (buttonIndex!=alertView.cancelButtonIndex) { // 「はい」のとき
        NSLog(@"直前url=%@",url);
        // リンクへ飛ぶ
        [[UIApplication sharedApplication] openURL:url]; // httpがあるので自動的にブラウザが立ち上がる
    }
}

- (void)dealloc
{
    webView.delegate=nil; // なんか必要なのだそうな
    if (url!=nil) [url release]; // copy属性だから
    [aview release];
    [webView release];
    [super dealloc];
}
画面の回転を有効にしている場合、回転ごとに内容の再読込をしないと画面幅が調整されない。

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
// 回転検出
{
    [webView reload]; // こうしないと画面幅が調整されないので
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // 回転有効
    return YES;
}
「重要」なこと。
UIWebViewで扱う文字エンコードはUTF-8にしないといけない。
HTML内のエンコード指定

とファイル自身の文字エンコードをUTF-8にするのを忘れないように。
(秀丸エディタだとファイル書き出し時に文字コードが指定できて楽。)