読者です 読者をやめる 読者になる 読者になる

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

「Windows Bridge for iOS」でUITableViewを使ったiOSアプリを変換できるのか試してみる その2

Windows Bridge for iOSは、Objective-Cで書かれたiOSアプリをWindowsアプリに変換するソリューションです。詳しくはこちらの記事を御覧ください。

UITableViewを使ったサンプルアプリをWindows Bridge for iOS SDKで変換して、きちんとWindows側で再現できているのか確認したところ画面が表示されていませんでした。

SDKの不備を疑っていろんなパターンで試してみたところ、UISplitViewControllerが未サポートなのが発覚しました。

この前書いた記事と完全に被ることになりますが、改めてWindows Bridge for iOS SDKを使って UITableViewControllerを表示させるところまでを検証してみたいと思います。

Master-Detail Applicationで作成したプロジェクトを変換する

前述した通り、XcodeでMaster-Detail Applicationのウィザードを使用して作成したアプリをWindows Bridge for iOSで変換するとどうなるのか試してみました。

ナビゲーションバーに表示された[+]ボタンをタップするとアプリに現在時刻が追加されていくというサンプルアプリです

Master-Detail Applicationで作成したプロジェクトを作成する(UISplitViewControllerを削除する)

Xcodeのウィザードで新規にMaster-Detail Applicationのプロジェクトを作成します。

Main.storyboardを開いて、不要なSplitViewとiPad用のViewControllerをバッと削除します。

f:id:ch3cooh393:20160718014908p:plain

iPhone用のUINavigationViewController側にIs Initial View Controllerのフラグをtrueにします。

f:id:ch3cooh393:20160718015049p:plain

AppDelegate.mのUISplitViewControllerDelegate部分を削除します。

@interface AppDelegate () <UISplitViewControllerDelegate>

@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
    splitViewController.delegate = self;
    return YES;
}

#pragma mark - Split view

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
    if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;
    } else {
        return NO;
    }
}

UISplitViewControllerDelegateをあつかっている部分は不要になったので全て削除します。

@interface AppDelegate ()

@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//    // Override point for customization after application launch.
//    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
//    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
//    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
//    splitViewController.delegate = self;
    return YES;
}

Windows側に戻り、Windows Bridge for iOSを使ってプロジェクトを変換して実行しみました。ナビゲーションバーの[Add]ボタンをクリックするとセルが追加されていきます。想定通りの挙動です。

f:id:ch3cooh393:20160718014554g:plain

iPhoneシミュレータと並べてみました。標準のUITableVieCellのスタイルを使用していることもあって、再現性が高いことが分かります。

f:id:ch3cooh393:20160718014638p:plain

ここまでは前回までの検証で実行できることがわかっています。これで終わると愛想がないのでもう少し検証してみましょう。

セルに画像を表示させる

xcassetsから画像を抽出する処理が必要だし、さすがに[UIImage imageNamed:]は実装されてないだろう……みたいなノリでUITableViewCellに画像を表示させてみましょう。

.xcassetsにインコのアイコンを追加します。

f:id:ch3cooh393:20160718015933p:plain

アセットから画像を取得して、UITableViewCellのimageViewに画像を指定します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    UIImage *image = [UIImage imageNamed:@"chiich4_1"];
    
    NSDate *object = self.objects[indexPath.row];
    cell.textLabel.text = [object description];
    cell.imageView.image = image;
    
    return cell;
}

iPhoneシミュレータで実行してみました。きちんと表示できることを確認しました。

f:id:ch3cooh393:20160718015818p:plain

Windowsでもきちんと変換できています。いい感じです。

f:id:ch3cooh393:20160718015801p:plain

さらに調子にのってAuto Layoutでレイアウトを定義されたカスタムセルを表示させてみましょう。

UITableViewにカスタムセルを表示できるかを検証する

セルに画像を表示することができたので調子に乗ってAuto Layoutで書かれたカスタムセルを表示できるか確認してみましょう。

UITableView#registerNibを使って外部xibでカスタムセルのレイアウトを定義する

MasterViewController.mにコードを足します。

- (void)viewDidLoad {
    [super viewDidLoad];
    
...省略...

    self.tableView.rowHeight = 240;
    [self.tableView registerNib:[UINib nibWithNibName:@"InkoTableViewCell" bundle:nil] forCellReuseIdentifier:@"InkoCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"InkoCell" forIndexPath:indexPath];
    return cell;
}

Windows Bridge for iOS SDKで、Auto Layoutを正しく解釈できていないと表示できないセルを作ります。……と言ってもViewを3分割してバラバラの背景色をしてその上に画像を配置しただけのものです。

f:id:ch3cooh393:20160718022040p:plain

さて、これでうまく表示できるのか、試してみましょう。

f:id:ch3cooh393:20160718022533p:plain

残念でした。xibファイルが正しく解釈されていないのかもしれません。

[Add]ボタンをクリックすると何かのセルが増えているようで、スクロールするとUITableViewのcontentSizeが増えていることがわかります。

UITableViewと同じstoryboardにカスタムセルを定義してみる

外部xibでカスタムセルを定義しているのが悪いのかな?と思い、storyboardの方にセルのレイアウトを移動させました。

f:id:ch3cooh393:20160718023720p:plain

Windows側で変換して実行してみました。左側はiPhoneシミュレータでの実行結果です。Windows側にはなにかが表示されていることは分かりますが、肝心のカスタムセルは表示されていませんでした。

f:id:ch3cooh393:20160718023800p:plain

カスタムセルをAuto Layoutで定義すると、Windows Bridge for iOSでは正しく解釈されないのかもしれないですね。

UIView#addSubViewを使うときちんと表示されることは確認しているのでカスタムセルを作る際はコードで実装するのが一番の安牌かもしれません。

関連記事

このエントリでは、Windows Bridge for iOS (旧名: WinObjC)についてを紹介させていただきました。Windows Bridge for iOSは、Windows 10で使用できるようにブリッジさせて、Objective-CのコードやiOS APIを使ったコードを再利用するためのプロジェクトです。

この他にもWindows Bridge for iOSのネタを紹介しております。Tipsをまとめておりますのでこちらのページをご参照ください。