iOS 7 雑感

iOS7がリリースされました。

大幅にUIが変更されましたね。
さっそくXcode 5 Developer Previewをダウンロードして試しています。
Xcodeの完成度としてはまだまだな気がしますが、とりあえずシミュレータを起動して、基本的な動きや外観を見てみました。

事前に噂されていたようにUIは大幅にフラットなイメージに統一されています。エミュレータでは限定したアプリ(Safariや写真、設定など)しかありませんし、バックグラウンドのイメージも無い為、最初の印象は少々貧弱に感じてしまいました。しかしWWDCのKeynoteなどを見ているとけっこう上品な感じに仕上がっているように感じます。

さて、Xcodeを使いながら色々試しています。
ハッキリ言って「困った…」と感じています。

UIButtonやUIToolbarなど、標準のコントロールもフラットでシンプルなものになってしまいましたが、それに伴いサイズも変わってしまいました。
既にリリース済みのアプリをシミュレータで動かした所、レイアウトの変更を強く感じます。
また標準のUIがフラットになったため、今まで使っていたPNGなどによる立体的なボタンの画像などもiOS7用に作り直す必要があるかもしれません。
もちろんiOS6以前も対応とする場合には、同じiPhoneでも2種類のUIを用意しなければならないかもしれません。
iOS6ではNSLayoutConstraintなどがあるため比較的対応がし易いかもしれませんが、それ以前もとなると…

もう一つ気になったのが、iOS7では「レイアを積み重ねる」というコンセプトらしく、どうもステータスバーもそのレイアの一つになっているようです。今まではステータスバーを表示させるとその高さ分はアプリケーションの関知出来ないエリアでした。
ですがiOS7ではどうもその領域にもアプリケーションが描画する事ができて、その上にステータスバーが半透明でレイアを重ねるという形になるような気がします。
するとステータスバーを表示しているアプリは全てそれに沿ったレイアウトに変更しなければならなくなるかも知れません。たかだか20ポイント分なのですが、上部にギリギリまで何かを描画しているような場合には気を付けなければならないかもしれません。

朗報は、xcodeにおいてstoryboardを使ってレイアウトする場合に、下記画面の右側でUIをiOS7用かiOS6.1以前用かを切り替える事が出来るようになっているようです。

 

 

AdMobのカスタムイベント(i-mobile用)

AdMobのカスタムイベントを作ってみました。

 

     1	//
     2	//  IMobileCustomEventBanner.h
     3	//
     4	//  Created by Keiichi Okamoto on 2013/05/09.
     5	//  Copyright (c) 2013 FuturesVision. All rights reserved.
     6	//
     7
     8	#import <UIKit/UIKit.h>
     9	#import "GADCustomEventBanner.h"
    10	#import "GADCustomEventBannerDelegate.h"
    11	#import "imobileAds/IMobileAdDelegateProtocol.h"
    12	#import "imobileAds/IMAdWhirlBannerView.h"
    13
    14
    15	@interface IMobileCustomEventBanner :NSObject 
    16
    17	@property (nonatomic, retain) IMAdWhirlBannerView *imAdView;
    18
    19	@end

 


 

     1	//
     2	//  IMobileCustomEventBanner.m
     3	//
     4	//  Created by Keiichi Okamoto on 2013/05/09.
     5	//  Copyright (c) 2013 FuturesVision. All rights reserved.
     6	//
     7
     8	#import "IMobileCustomEventBanner.h"
     9
    10
    11	@implementation IMobileCustomEventBanner
    12
    13	@synthesize delegate = __delegate;
    14	@synthesize imAdView = __imAdView;
    15
    16
    17	- (void)requestBannerAd:(GADAdSize)adSize
    18	              parameter:(NSString *)serverParameter
    19	                  label:(NSString *)serverLabel
    20	                request:(GADCustomEventRequest *)request {
    21
    22	    NSString* val;
    23	    int publisherId = 0;
    24	    int mediaId = 0;
    25	    int spotId = 0;
    26	    NSArray* array;
    27	    array = [serverParameter componentsSeparatedByString:@","];
    28	    @try {
    29	        val = [array objectAtIndex:0];
    30	        publisherId = [val integerValue];
    31	        val = [array objectAtIndex:1];
    32	        mediaId = [val integerValue];
    33	        val = [array objectAtIndex:2];
    34	        spotId = [val integerValue];
    35	    }
    36	    @catch (NSException *exception) {
    37	        return;
    38	    }
    39	
    40	    CGRect frame;
    41	    frame = CGRectMake(0, 0, kIMAdViewDefaultWidth, kIMAdViewDefaultHeight);
    42	    
    43	    __imAdView = [IMAdWhirlBannerView imAdWhirlBannerViewWithFrame:frame
    44	                                                      withDelegate:self
    45	                                                          testMode:NO];
    46	    [__imAdView retain];
    47	    [__imAdView setWithPublisherId:publisherId
    48	                           mediaId:mediaId
    49	                            spotId:spotId
    50	                          testMode:NO];
    51	    [__imAdView start];
    52	
    53	}
    54	
    55	- (void)dealloc
    56	{
    57	    self.delegate = nil;
    58	    [__imAdView release];
    59	
    60	    [super dealloc];
    61	}
    62	
    63	
    64	#pragma IMobileAdDelegate
    65	
    66	- (void)imAdViewDidFinishReceiveAd:(IMobileAdView *)imobileAdView {
    67	    CGRect frame;
    68	    frame = imobileAdView.frame;
    69	    [self.delegate customEventBanner:self didReceiveAd:imobileAdView];
    70	}
    71	
    72	- (void)imAdViewDidFailToReceiveAd:(IMobileAdView *)imobileAdView {
    73	    [self.delegate customEventBanner:self didFailAd:nil];
    74	}
    75	@end

 

 

AdMobのメディエーション

AdMobがメディエーション機能の提供を始めるにあたって、AdWhirlのメディエーション機能が終息していくようなので広告を使う新規アプリや既存のアプリのメディエーションをAdMobに移行するように作業をしています。
そこで新たにi-mobileもインプリしようといていたのですが、どうでもいいトコでハマってしまいました。

AdMobのメディエーションの実装は非常に簡単で、アプリ側ではGADBannerViewを
インスタンス化してGADRequestを付けて

        [self.gadBannerView loadRequest:self.gadRequest];

としてやるだけです。

しかしハマってしまったのは

            gadBannerView = [gadBannerView initWithAdSize:kGADAdSizeBanner];

 

初期化メソッドを呼ぶ際にバナーのサイズを指定してやるのですが、ここでkGADAdSizeSmartBannerPortrait等を指定してやると、どうやらAdMobとiAdくらいしか表示してくれない…

https://developers.google.com/mobile-ads-sdk/docs/admob/mediationにも

Note: AdMob Ad Network Mediation does not fully support Smart Banners currently.

と書いてはあるのですが、どうやら殆どサポートされていないようです。
誤って設定すると、AdMobのメディエーションのレポート画面を見てもi-mobile等は設定した比率に合わせてリクエストは来ているのですが、impressionがゼロという状況になってしまいます。

Portraitの時はkGADAdSizeBannerを指定するべきです。
Landscapeの時は?どうやらPortrait用の広告は諦めるか、AdMobとiAdのみを表示するかと言う事しか無いようです。
元々、i-mobileは320×50しかサポートしていないトコに問題があるのですが、そういう場合には320×50の広告をセンタリングして表示するとか…

その他、 gadBannerView.rootViewController で指定すべきUIViewControllerにも何だか癖がありそう…

AdWhirlはオープンソースになっていたので、ある程度は自分で調整出来たのですが、AdMobはクローズドなので面倒です。
後は自分でCustomEventをハンドリングするようにしなければいけない?
面倒だなぁ。

UISplitViewControllerのMasterViewController (UIPopoverController) を表示する (備忘録)

 

 

UISplitViewController は MasterViewController (UIPopoverController) を表示する為の標準のAPIが提供されていません。またUISplitViewControllerからUIPopoverControllerの表示は通常の方法ではないようで、UIPopoverArrowDirectionも無く、横からスライドしてくるような表示になります。

そこでアプリケーションの中で強制的にUIPopoverControllerをUIPopoverControllerと同じように表示する方法をまとめます。

@property (nonatomic, retain) UIBarButtonItem* barButtonItem;

- (void)splitViewController:(UISplitViewController *)svc
     willHideViewController:(UIViewController *)aViewController
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)pc {

    barButtonItem.title = @"メニュー";
    [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
    self.masterPopoverController = pc;
    self.barButtonItem = barButtonItem;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [__barButtonItem.target performSelector:__barButtonItem.action
                                 withObject:__barButtonItem];
}

Sketch Camera 1.1 をリリースしました

Sketch Camera 1.1 をリリースしました。

AppStore

 

新機能は以下の通りです。

  • iPad と iPad mini対応
  • モノクロ効果のサポート
  • セピア効果のサポート
  • 問題修正

 

 

ポケット定規+

 

 ポケット定規+ 2.1 をリリースしました。
  AppStore
  • iPhone 5、iPod Touch(5 gen)のサポート
  • iPad miniのサポート
  • 目盛りの色変更

ポケット定規+には広告は表示されません。

ポケット定規

ポケット定規 2.1 をリリースしました。

AppStore

  • iPhone 5、iPod Touch(5 gen)のサポート
  • iPad miniのサポート
  • 目盛りの色変更

ポケット定規には広告が表示されます。

 

iOS Developer Programの更新

そろそろ時期がやってきたようで、iOS Developer Programの更新の案内が来ました。

少し前から気になっていたのが昨今の円安で、円建ての年会費が上がってしまうのでは?と言う事です。
しかし今現在では8400円(消費税込み)。去年より100円安くなっています。
今の契約が切れるのは4月ですのでまだ時間がありますが、円安が反映されないうちに更新しちゃいます。

 

Blender → SIO2 (備忘録)

Blenderで作った3DモデルをSIO2に持って行く際に、Blender上でattache出来たと思っていたTexture (Material)をSIO2側で実行すると上手く行かない事がありました。その際に注意すべき点を備忘録として書き残しておきます。

  • SIO2にTextureを持って行く為にはBlender上でUVマップにUnwrapしておく必要があります。
  • Blenderではメッシュは全てQuadで作成されます。これはOpenGLの仕様の違いだと思います。OpenGL ESではTriangleでレンダリングして行く必要があるため各オブジェクトはExportする前に変換しておく必要があります。
    1. オブジェクトを選択する
    2. Edit Modeに入る。
    3. Meshメニューから “Faces” -> “Quad to Tri” を選び実行する。

    以上

 

 

SiGNAL Attack をリリースしました

SiGNAL Attack 1.0をリリースしました。

AppStore

シンプルなパズルゲームです。