ウェブブラウザの作成

2010. 05. 12
引き続き『基礎からのiPhone SDK 改訂版』を読み進めますが、本章ではウェブブラウザを作りながらObjective-Cの基礎や文字列(NSString)、デリゲートの話が間に入って若干読み難い構成ですので、一通りウェブブラウザを作った後で補完していこうと思います。


●サンプルアプリケーションの概要

271

今回作るウェブブラウザは、URL入力・表示用とページ閲覧制御用のツールバーを2つ、その間にウェブビューを配置するもので、機能的にはシンプルながら簡単にウェブブラウザが作れることが分かる内容です。

もちろん、本章の中で説明しているObjective-CやNSStringなどがある程度頭に入っている上での感想で、1冊目として読むと辛い部分があると思います。

そういう意味でも1冊目『iPhone SDKの教科書』→2冊目『基礎からのiPhone SDK 改訂版』の方が入り易いかもしれません。


●プロジェクトの作成

Window-based Applicationテンプレートで、プロジェクト名を『Web』とします。

272


●nibファイルの編集

nibファイル MainWindow.xibをダブルクリックしてInterface Builderを起動します。

本書では下のツールバーと真ん中のウェブビューを配置・設定後に上のツールバーを設置していますが、ウェブビューは設置時に可変するので僅かな手間を惜しむなら、上下のツールバーを置いてからウェブビューを置いた方が調整の手間が省けます。

Libraryウィンドウからドラッグ&ドロップで、Toolbar2つ、その間にWeb Viewを置きます。

273


・ウェブビューの設定

274

(本書の図がデフォルト状態の図なので紛らわしいのですが)InspectorウィンドウのWeb Viewで『Scales Page To Fit(拡縮表示でページの横幅を画面に合わせる)』をチェックし、『Detects Phone Numbers(電話番号らしき数字を判別するか)』のチェックを外します。


・下ツールバーの編集

デフォルトでバーボタンが1つありますが、今回は左側から

1)バックボタン(前のページに戻る)
2)フォワードボタン(先のページに進む)
3)アクティビティインジケータ(読み込み中であることの表示)
4)スペーサ(Flexible Space Bar Button Item)
5)リフレッシュボタン(ページを再読み込みする)
6)ストップボタン(読み込みを中止)

というアイテムを並べます。

1)バックボタン

一つ目のボタン(Bar Button Item)はデフォルトで付いているので、Viewウィンドウのボタンをダブルクリックして『Item』という文字列を『Back』に変更します。

2)フォワードボタン

バックボタンの右側にBar Button Itemを置き、『Item』を『Forward』に変更します。

3)アクティビティインジケータ

本書では後半に設置していますが、ここで置いておきます。

Bar Button Itemと異なり、アクティビティインジケータはツールバーに直置きできず、Viewアイテムの上に置く必要があります。

フォワードボタンの右側にViewを置き、正方形になるよう幅を33.0に調整します。

その上にActivity Indicator Viewを置き、InspectorウィンドウのSizeタブの下方にあるPlacementのボタンを両方押して、アクティビティインジケータをViewに対してセンタリングします。

275

DocumentウィンドウでViewを選択(Viewウィンドウで選択しても同じなのですが、Documentウィンドウの方が早い気がします)して、Viewを透明化します。

276

InspectorウィンドウのAttributesタブを開き、BackgroundをクリックしてColorsウィンドウを開き、Opacity(不透明度)を0%にします。

277

本書の説明ではDrawingのOpaqueのチェックを外すとViewを透明化できるとあるのですが、私の環境ではBackgroundのOpacityに依存するようで、Opaqueのチェックの有無は関係ありませんでした。
(iPhone Simulatorに起こる現象かもしれません。諸事情により現在実機で確認できないので、後日調べてみます)

278

念のため、Opaqueのチェックは外しておきます。

次にインジケータを見栄えの良い白にします。

DocumentウィンドウでGray Activity Indicatorを選択し、InspectorウィンドウでStyleをWhiteにします。

また、アプリ起動時およびインジケータが非アクティブの時に見えないようにするため、Hide When Stoppedをチェックします。
(Hide When Stoppedにチェックを入れると、ViewのDrawingのHiddenにも自動でチェックが入るのですが、入らなければチェックしてください)

279

4)スペーサ

リフレッシュボタンとストップボタンを右寄せにするためのスペーサを入れます。

Flexible SpaceBar Button Itemをアクティビティインジケータの右側に設置します。

280

5)リフレッシュボタン

Bar Button Itemをスペーサの右側に置き、InspectorウィンドウでStyleをPlainに、IdentifierをRefreshにします。

281

6)ストップボタン

Bar Button Itemをリフレッシュボタンの右側に置き、InspectorウィンドウでStyleをPlainに、IdentifierをStopにします。

282

283

・上ツールバーの編集

デフォルトのボタンを削除して、URL入力・表示用のテキストフィールドを設置します。

ボタンは、Viewウィンドウでボタンをドラッグしてウィンドウ外で離すと消えます。

Text Fieldをドラッグ&ドロップで置き、幅を300.0くらいにし、センタリングしたければテキストフィールドの両側にFlexible Space Bar Button Itemを入れると良いでしょう。

284

Inspectorウィンドウで、未入力時のテキストを表示するPlaceholderを『URL』に、Text Input Traits欄でCorrection(入力時の自動補正)を『No』に、Keyboardを『URL』に、Return Keyを『Go』にします。

286

これでレイアウトは完成です。

Documentウィンドウは下図のようになります。

285


●アクション

続いてアクションの接続をします。

今回の場合、アプリケーションの動作の起点となるのは、

1)バックボタン
2)フォワードボタン
3)リフレッシュボタン
4)ストップボタン
5)URLテキストフィールドへの入力

となります。

本書ではInspectorウィンドウから接続していますが、ViewウィンドウのUIWebViewを右クリックしてConnectionsパネルから行うこともできます。

287

ConnectionsパネルのReceived Actionsの各項目をViewウィンドウの各ボタンへ接続します。

goBackバックボタン
goForwardフォワードボタン
reloadリフレッシュボタン
stopLoadingストップボタン

URLテキストフィールドのアクションは手動でアクションを設定する必要があります。

XcodeのWebAppDelegate.hにアクションメソッドの宣言を追加します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

@interface WebAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

- (IBAction)loadUrl:(id)sender;    // ウェブページの読み込み

@end

288

Interface Builderに戻り、DocumentウィンドウのWeb App Delegateを右クリックしてConnectionsパネルを開くと、先程追加したloadUrl:がReceived Actionsに追加されていますので、URLテキストフィールドに接続、サブメニューから『Did Ens on Exit』を選択します。

289


●アウトレット

次にアウトレットの設定を行います。

今回の場合、プログラムが応答する対象となるのは、

1)ウェブビュー
2)アクティビティインジケータ
3)URLテキストフィールド
4)バックボタン
5)フォワードボタン
6)リフレッシュボタン
7)ストップボタン

となります。

ただし、リフレッシュボタンとストップボタンは、Toolbarの標準ボタンを採用しているせいか、アウトレットとしての指定をしなくても済むようです。

残りの項目に付いて、まずXcodeのWebAppDelegate.hにアウトレットの宣言を追加します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

@interface WebAppDelegate : NSObject <UIApplicationDelegate> {
    IBOutlet UIWebView *webView;    // ウェブビュー
    IBOutlet UIActivityIndicatorView *activeView;    // アクティビティインジケータ
    IBOutlet UITextField *urlField;    // URLテキストフィールド
    IBOutlet UIBarButtonItem *backButton;    // バックボタン
    IBOutlet UIBarButtonItem *fwdButton;    // フォワードボタン

    UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

- (IBAction)loadUrl:(id)sender;    // ウェブページの読み込み

@end

290

Interface Builderに戻り、DocumentウィンドウのWeb App Delegateを右クリックしてConnectionsパネルを開くと、先程追加したアウトレットがOutletsに追加されていますので、Viewウィンドウの各アイテムと接続します。

291


●UIWebViewのデリゲートの接続

ViewウィンドウのUIWebViewを右クリックしてConnectionsパネルを開き、OutletsのdelegateをDocumentウィンドウのWeb App Delegateに接続します。

298


●メソッドの実装

最後にメソッドの実装を行います。

各クラスメソッドの詳細は後日改めて行うとして、実装するメソッドの概要とコードについて説明します。

新規追加するメソッドが5つ、テンプレートで作られている既存メソッド(application:didFinishLaunchingWithOptions:)内への追加が1つあります。

1)application:didFinishLaunchingWithOptions:
アプリケーションの起動処理終了後、デフォルトのURLをウェブビューで開きます

2)loadUrl:
URLテキストフィールドで入力されたURLをウェブビューで開きます

3)webView:shouldStartLoadWithRequest:
URLをウェブビューで開く前に、開くかどうかの可否を判断します

4)updateWebBrowser:
アクティビティインジケータとURLテキストフィールドの更新、バック・フォワードボタンの有効・無効の判断をします

5)webViewDidStartLoad:
ウェブビューで読み込みが開始されたことを通知します

6)webViewDidFinishLoad:
ウェブビューの読み込みが完了したことを通知します

※本書では『5)webViewDidStartLoad:』の後に『4)updateWebBrowser:』を説明していますが、その順番で記述するとコンパイルエラーが出ます。
(webViewDidStartLoad:がupdateWebBrowser:を呼び出しているため)


・デフォルトURLでウェブビューを開く

本書ではapplicationDidFinishLaunching:メソッドですが、『アプリケーションのライフサイクル(2)』で説明しているように、現在はapplicationDidFinishLaunching:メソッドの代わりにapplication:didFinishLaunchingWithOptions:メソッドを使っています。
(太字が追加した部分)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch

    // デフォルトのURLを読み込む
    NSURL *url = [NSURL URLWithString:@"http://www.idolmaster.jp/imas/"];
    NSURLRequest *urlReq = [NSURLRequest requestWithURL:url];
    [webView loadRequest:urlReq];


    [window makeKeyAndVisible];

    return YES;
}

292

ここでは文字列をNSURLオブジェクト(url)にし、さらにNSURLRequestオブジェクト(urlReq)にしてウェブビュー(webView)に読み込みを要請しています。


・URLテキストフィールドで入力されたURLをウェブビューで開く

- (IBAction)loadUrl:(UITextField *)sender {

    // テキストフィールドから文字列を取得する
    NSString *urlStr = [sender text];
    
    // 文字列からURLクラスのインスタンスを生成する
    NSURL *url = [NSURL URLWithString:urlStr];
    
    // URLからURLリクエストのインスタンスを生成する
    NSURLRequest *urlReq = [NSURLRequest requestWithURL:url];
    
    // ウィブビューにウェブページ読み込みを指示する
    [webView loadRequest:urlReq];
}

293

デフォルトURL同様、URLテキストフィールドで入力された文字列はNSStringオブジェクト(urlStr)として受け取りますが、NSURLオブジェクト(url)にし、さらにNSURLRequestオブジェクト(urlReq)にしてウェブビュー(webView)に読み込みを要請しています。


・ウェブビューを開くかどうかの判別

- (BOOL)webView:(UIWebView *)view shouldStartLoadWithRequest:(NSURLRequest *)req navigationType:(UIWebViewNavigationType)navType {
    if ([[[req URL] host] isEqualToString:@"www.ng.com"]) {
        return(NO);    // 拒否
    }
    return(YES);    // 許可
}

295

ウェブビューがNSURLRequestオブジェクトを受け取って、実際に読み込む前の処理を記述しています。

今回の場合は、『www.ng.com』というサーバへのアクセスを拒否することにしています。


・ブラウザの更新

- (void)updateWebBrowser {

    // アクティビティインジケータの更新
    BOOL loading = webView.loading;
    BOOL animating = [activeView isAnimating];

    if ((loading == YES) && (animating == NO)) {
        [activeView startAnimating];
    } else if ((loading == NO) && (animating == YES)) {
        [activeView stopAnimating];
    }

    // URL表示のテキストフィールド更新
    NSURL *url = [webView.request URL];    // URLを取得
    NSString *urlStr = [url absoluteString];    // URLからフルパスを取得
    urlField.text = urlStr;    // UITextFieldを変更

    // [戻る][進む]ボタンのEnabled制御
    backButton.enabled = webView.canGoBack;
    fwdButton.enabled = webView.canGoForward;
}

294

アクティビティインジケータの更新は、ウェブビューが読み込み中であるか(loading)とインジケータが表示中であるか(animating)という2つのパラメータで判断し、表示の有無を判別しています。

URLの更新は『デフォルトURLでウェブビューを開く』などとは逆に、読み込んでいるウェブビューからNSURLオブジェクト(url)を取得し、NSStringオブジェクト(urlStr)に変換、さらにテキストにしてURLテキストフィールドに返しています。

バック・フォワードボタンの制御は、ウェブビューの状態から『戻る』もしくは『進む』ことが可能かどうか判断し、各ボタンの有効・無効を制御しています。


・ウェブビュー読み込み開始の通知

- (void)webViewDidStartLoad:(UIWebView *)view {
    [self updateWebBrowser];    // ウェブブラウザ更新
}

296

ウェブビューの読み込み開始判別が済み、読み込みを開始した通知を受けた時の処理を記述します。

ここではupdateWebBrowser:メソッドを呼び出しています。


・ウェブビュー読み込み終了の通知

- (void)webViewDidFinishLoad:(UIWebView *)view {
    [self updateWebBrowser];    // ウェブブラウザ更新
}

297

本書では
[self updateWebBrowser:view];
となっていますが、『:view』は不要です。

ウェブビューの読み込みが終了した通知を受けた時の処理を記述します。

ここではupdateWebBrowser:メソッドを呼び出しています。


●ビルドと実行

簡易機能しかありませんが、ウェブブラウザとして機能しています。

271

ちなみに『ウェブビューを開くかどうかの判別』で指定した『http://www.ng.com』を入力しても何も起こりません。
(ウェブビューを更新しないので、見た目の変化が起こりません)

299

取り敢えずアプリケーションができましたので、次回から中身について掘り下げようと思います。



参考文献

基礎からのiOS SDK基礎からのiOS SDK
(2010/10/09)
鶴薗 賢吾、松浦 健一郎 他

商品詳細を見る






QuietControl 30 wireless headphones
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
04 | 2017/05 | 06
Sun Mon Tue Wed Thu Fri Sat
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

QuietControl 30 wireless headphones
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR