2016年7月7日木曜日

CoreImage Filterの種類

iOS9、OS X 10.11現在のフィルター一覧。
元情報はアップルのフィルタリファレンス
よくわからないのや、言葉で言い表しにくいのもあるが、いろいろOSで用意してるのだな。

CICategoryBlur

ブラー(ぼかし)関係

CICategoryColorAdjustment

色調関係の変更

CICategoryColorEffect

カラーエフェクト

CICategoryCompositeOperation

Photoshopのレイヤーの合成にある合成処理がだいたいあるみたい。

CICategoryDistortionEffect

PhotoBoothとかで使われてる感じのエフェクト
  • CIBumpDistortion
    • 凹凸エフェクト
  • CIBumpDistortionLinear
    • びろーんって伸びる
  • CICircleSplashDistortion
    • 光のトンネル。中央を残して周辺が放射状にびろーん
  • CICircularWrap
    • 二次元的に円形に曲げる。(文字の変形とかでよくあるやつ)
  • CIDroste
    • 合わせ鏡のような
  • CIDisplacementDistortion
    • 2枚を合成して複雑な画像に(グレースケール?)
  • CIGlassDistortion
    • ガラス窓エフェクト
      • こんな感じのテクスチャー画像が必要なことまではわかった。(参考サイト)ただ、自分でPhotoshopのフィルターで似たような画像を作って試してみても、なかなかきれいなエフェクトがかからない。できるだけランダムで均一にばらけた画像がいいんじゃないかとは思うのだが…。
  • CIGlassLozenge
    • 菱形ガラス窓?(中央に形に沿った歪みを?)
  • CIHoleDistortion
    • ブラックホールみたいのを表示
  • CILightTunnel
    • PhotoBoothでの「光のトンネル」。中心を残して、周囲を伸ばしてトンネル状に見せたり、らせん状にぐるぐる歪める
  • CIPinchDistortion
    • つまんだような歪み
  • CIStretchCrop
    • 縦横にストレッチし、クロップも
  • CITorusLensDistortion
    • 丸いレンズ状の歪み
  • CITwirlDistortion
    • 渦巻き?
  • CIVortexDistortion
    • 渦巻き

CICategoryGenerator

バーコードやQRコード、画像パターンを作る

CICategoryGeometryAdjustment

画像の傾きやサイズ、回転など?

CICategoryGradient

グラデーション関係

CICategoryHalftoneEffect

パターン作成
  • CICircularScreen
    • 同心円状のパターン作成
  • CICMYKHalftone
    • 画像を、CMYKの印刷網掛けしたような画像に変換
  • CIDotScreen
    • スクリーントーンのような網掛けパターン作成
  • CIHatchedScreen
    • もっと細かいスクリーントーンのような網掛け作成
  • CILineScreen
    • 直線のスクリーントーンのような網掛け作成

CICategoryReduction

画像解析関係?

CICategorySharpen

シャープ処理

CICategoryStylize

Photoshopなどにあるようなフィルターの一部
  • CIBlendWithAlphaMask
    • 画像Aをα付きマスク画像で抜いて画像Bに重ねる
  • CIBlendWithMask
    • 画像Aをマスクで抜いて画像Bとブレンド
  • CIBloom
    • Photoshopでいう光彩拡散。ソフトエッジ&グロー処理。全体が薄く輝いてるっぽい画像になる
  • CIComicEffect
    • ポップなイラスト調になる
    • よく画像加工アプリにある、白黒の輪郭+スクリーントーンのようなものじゃない
    • 調整できるパラメータが一切ないので、単体では柔軟な使い方はできない
    • 網をかけたりする都合上、ある程度大きな画像じゃないときれいにならないかも
  • CIConvolution3X3
    • 3x3ピクセルの計算でエッジを際立たせたり、色を変えたり?
  • CIConvolution5X5
    • 5x5ピクセルの計算でエッジを二重にするなど色々?
  • CIConvolution7X7
    • 7x7ピクセルの計算で粗くするなど色々?
  • CIConvolution9Horizontal
    • 9つの要素を指定して水平方向を複雑化?
  • CIConvolution9Vertical
    • 9つの要素を指定して垂直方向を複雑化?
  • CICrystallize
    • Photoshopでいう水晶フィルター
  • CIDepthOfField
    • 被写界深度を変えたような処理
  • CIEdges
    • Photoshopでいうエッジの光彩
  • CIEdgeWork
    • Photoshopでいうスタンプフィルタ? 版画のような粗い画像にする。
  • CIGloom
    • ハイライトを眠たくする
  • CIHeightFieldFromMask
    • マスク画像の白抜き部分にグレースケールのインナーグロー処理をする?
  • CIHexagonalPixellate
    • 6角形のモザイク化
  • CIHighlightShadowAdjust
    • ハイライトとシャドウの変更
  • CILineOverlay
    • 輪郭検出してモノクロに?
  • CIPixellate
    • 四角いモザイク処理
  • CIPointillize
    • 点描っぽい?
  • CIShadedMaterial
    • (金属的な?)質感を出すシェード処理?
  • CISpotColor
    • 階調を落として色を変更?
  • CISpotLight
    • 指定箇所にスポットライトを当てたように、周囲を暗く

CICategoryTileEffect

タイルパターンを作る処理

CICategoryTransition

トランジション(場面転換)処理いろいろ

CoreImageの使い方基礎

CoreImageの機能と概要

  • フィルタ(リファレンスにリンク)
    • ぼかしとか、画像にかけるエフェクト
  • フィルタグラフ
    • フィルタの組み合わせで複雑なエフェクトを実現(?)
  • プラグインアーキテクチャ
    • システム提供のフィルタと、ユーザー自作フィルタを組み合わせて機能を拡張できる
  • ほとんどのハードウェア上で動作するように書かれてる
  • 必要とされる時までできるだけ実行を遅らせるので、メモリ確保が直前とかがある
  • コンテキスト( context)というオブジェクトが必要
    • 必要なメモリ割当、フィルタのカーネルをコンパイルして実行など、いろいろ使えるらしい
  • 座標は左下が0,0で、右上に行くに従って増える。SpriteKitなんかと一緒で、UIImageとは上下が逆になる。

フィルタのかけ方

  1. フィルタの作成と設定
  2. ソースイメージをフィルタに渡す
  3. フィルタ処理した画像を得る
コードは以下。
思ったよりも難しくないね。フィルタ名とパラメータの扱いがわかればどんどんいけそう?

//元画像作成
let uiInputImage = UIImage(named: "イメージ名") //UIImage作成
let ciInputImage = CIImage(image: uiInputImage!) //CIImageに変換
        
//*******フィルタの作成と設定(例:モノクロフィルタ)*******
let filter = CIFilter(name: "CIColorMonochrome"//フィルタ作成
filter!.setValue(image, forKey: kCIInputImageKey) //フィルタに画像渡す
filter?.setValue(CIColor(red: 1.0, green: 1.0, blue: 0), forKey: kCIInputColorKey) //フィルタパラメータ設定
filter?.setValue(1.0, forKey: kCIInputIntensityKey) //フィルタパラメータ設定

//フィルタ処理した画像を得る
//******CIContext作成*******
//これ使って一度CGImageに直した方がいろいろいいらしい
let ciContext = CIContext(options: nil) //nilで作成
let cgImage = ciContext.createCGImage((vignetteFilter?.outputImage)!, fromRect: ciInputImage!.extent)
//最後のextentってのはUIImageでいうboundsみたいな値らしい?
        
//*******CGImageからUIImageに変換******
let uiImage = UIImage(CGImage: cgImage) //UIImageに変換
myImageView.image = uiImage

フィルタ処理後のイメージを得る

monochromeFilter!.outputImage
でCIImageが得られるので、それをUIImageに再変換して表示したり、そのまま次のフィルタ処理に回したりする。

Context使ったほうがいいらしい

直接CIImageをUIImageに変換した場合、UIImageに設定してたものが無視されたりするんだそうな。
それを回避するため、一度CIContextを使ってCGImageに変換してからのほうがいいんだそうな。

パラメータはkeyを使って設定

フィルタの設定はkeyによってどのパラメータをいじるかを指定するわけだが、多くのkeyに対してはkCIで始まるStringが定義されているので、それを使えばいいし、定義されていないKeyがあれば" "で囲んだStringで指定してやればいい。
  • 以下はどちらでも可
    • monochromeFilter?.setValue(1.0, forKey: kCIInputIntensityKey)
    • monochromeFilter?.setValue(1.0, forKey: "InputIntensityKey")
数値は厳密にはNSNumberの値なのだが、そのまま直接数値を指定する分には問題なさそう。
乱数とか、事前に計算の要素を入れた場合は、以下のように型に気をつけないといけない。
    let scale = NSNumber(double: Double(arc4random() % 40) / 10) //0〜4までの整数値
    filter?.setValue(scale, forKey: kCIInputScaleKey)

    フィルタ作成時にパラメータを一度に並べて指定することもできる
    let monochromeFilter = CIFilter(name: "CIColorMonochrome",
                           withInputParameters:
                           ["inputColor" : sepiaColor,
                            "inputIntensity" : 1.0])

    座標は元画像の大きさを、CIVectorで指定

    パラメータで座標を指定する場合があるが、その場合は最終的に表示されるUIImageの大きさを基準にするのでなく、元画像の大きさで指定する。
    出力先が640x480のサイズでも、オリジナル画像が1000x500だったら、中心部分を指定するには500,250の位置を指定する。
    sourceImage.size.widthと.heightを使って求められるわな。

    指定時はCIVector(x, y)でやらないといけない。
    filter?.setValue(CIVector(x: centerX, y: centerY), forKey: kCIInputCenterKey)

    2016年7月1日金曜日

    All interface orientations must be supported〜とか出る

    以前リリースしたアプリをアップデートしようとしたら、以下の2つのWarningが出てしまった。

    warning: All interface orientations must be supported unless the app requires full screen.
    warning: A launch storyboard or xib must be provided unless the app requires full screen.

    ネット翻訳したら、
    アプリがフルスクリーンを必要としない限り、すべてのインターフェースの向きがサポートされなければなりません。
    アプリがフルスクリーンを必要としない限り、ラウンチストーリーボードまたはxibは提供されなければなりません。

    だそうだ。よくわからん。
    どうも、iOS9になってSplitViewとかいろいろ対応したせいで、原則的にすべての向き(ポートレート、ランドスケープ)の画面をサポートしなければいけないらしい。
    しかしあくまでもフルスクリーンを必要としない限り。
    というわけで、TARGETSのところのRequires full screenをチェックして再ビルドしたら消えてくれたよ。
    めんどくせぇな。

    2016年6月27日月曜日

    GoogleのAdMobを組み込む

    iAdが廃止になり、サードパーティ製の広告サービスの組み込みが必須になったので、GoogleのAdMobというのを組み込むことにした。
    はやりのインターステーシャル広告とかなんとかにも対応してる。

    以前はリリース済みアプリじゃないと広告が表示できなかったようだが、現在はリリース前のものにも組み込めるようになったようだ。(リリース後にAdMobの管理画面でAppStoreの情報とリンクさせる必要はある)

    概要

    やることは以下のように単純。
    • AdMobのFrameworkをプロジェクトにインポートする
    • クラスの先頭で import GoogleMobileAds する
    • StoryboardもしくはコードからGADBannerViewクラスのオブジェクトを作って表示させる
    Firebaseというモバイルサービスプラットフォームの一部なのだそうだが、説明が英語なのでよくわかってない。
    とりあえずFirebaseを設定しなくても広告は表示できるようなので、わかったら追記したい。

    手順

    AdMobのアカウントを作成

    AdMobのサイトでアカウントを作成する。
    細かいやり方は略す。

    アプリを追加

    • 新しいアプリの収益化
      • AppStoreにリリース済みのアプリを、アプリ名や開発者名で検索して選択
    • 広告フォーマットを選択
      • 通常のバナー広告(画面隅に出しとくアレ)
      • インターステーシャル広告(アプリの場面切り替え時などに表示する全面広告)
      • ネイティブ広告(デバイスに最適な広告を表示してくれるらしいが、まだよくわからん)
      • ……などを選ぶ
    • Firebaseアナリティクスの設定
      • 新しい広告向けのアクセス解析サービスだが、設定方法がまだよくわからん
    • SDKのインストール
      • 詳細は以下に

    SDKのインストール

    「表示の設定方法」にリンクされてるGoogle Mobile Ads SDKのページで googlemobileadssdkios.zip ってのをダウンロード。

    次にXcodeにインストールするのだが…
    以前は日本語でとってもやさしく説明してくれてたページ(この辺?)があったんだけど、現バージョンについてはFirebaseの英語ページしか出てこん!? 探す!
    とりあえずこちらのページを参考にする。



    必ずコピーすること
    Xcodeの左側のファイルインスペクタからアプリ名を右クリックして、Add Files to "アプリ名"...を選び、ダイアログから、ダウンロードしたAdMobSDKのフォルダの中のGoogleMobileAds.frameworkをインストールする。
    この際、ダイアログ下にあるOptionsボタンを押し、Copy items if neededをチェックすること。そうしないとframeworkへのリンクが貼られるだけとなるため、frameworkのファイルを移動したり捨てたりすると機能しなくなっちゃう。

    とりあえずしなくてもいいこと?

    GoogleService-Info.plistを入手

    正式にはアプリに関する構成情報を格納するGoogleService-Info.plistというファイルを使用するそうである。
    入手するにはFirebase consoleにログインしてアプリを登録するか、もしくはサンプルの同.plistファイルをダウンロードし、プロジェクトと同じディレクトリーに保存するのだそうだ。
    重要:GoogleService-Info.plistファイルは広告のUnit IDを保存しません。あなたは他の手段で広告のUnit IDを格納、読み出さなければなりません。 
    しかし、Firebaseの方も英語の説明しかないので、よくわからない。
    とりあえずFirebaseとか.plistファイルとかを考えなくても広告は表示できるようなので、無視しておこう。

    Podfileを作る

    プロジェクトと同じディレクトリに、以下の内容を含むPodfileというファイルを作れとある。
    source 'https://github.com/CocoaPods/Specs.git'
    
    platform :ios, '7.0'
    
    target 'BannerExample' do
      pod 'Firebase/Core'
      pod 'Firebase/AdMob'
    end

    pod installの実行

    ターミナルから同じディレクトリのpod installを実行してください。
    インストールが終わったらプロジェクトを閉じ、プロジェクト名.xcworkspaceを開いてください。
    あなたのプロジェクトファイルはFirebaseとAdMobのために新しいPodsプロジェクトを含まねばなりません。
    …とあるんだが、これも無視してもできたようだ。

    コードからGADBannerViewを参照する

    こっからはまたちゃんと作業すること。

    広告を表示するViewControllerの先頭でGoogleMobileAdsをimportする。

    • Swiftの場合
      • import GoogleMobileAds
    • Objective-Cの場合
      • #import <GoogleMobileAds/GoogleMobileAds.h>

    StoryboardでAdMobのUIViewを貼る方法と、コードから作る方法と2通りあるのはiOSの他の部品と一緒だ。
    Storyboardで貼るなら、UIViewをドラッグして配置し、カスタムクラスを GADBannerView に設定する。Outletも引っ張って変数を作っとくこと。

    アプリIDを書き込む

    AppDelegate.swiftにアプリIDを書き込む。AdMobにアプリを登録した時に表示されるやつ。
    なくても表示されるみたいなんだけど、入れとけ。
    注意:次に説明する広告ユニットIDとは別物!
    アプリID
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        GADMobileAds.configure(withApplicationID: "ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx")
        return true
    }

    広告をGADBannerViewに読み込む

    最後に、バナー広告を表示させるViewControllerにコードを加えよう。

    Storyboardで作った場合

    override func viewDidLoad() {
      super.viewDidLoad()
    
      print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
      adMobBanner.adUnitID = "ca-app-pub-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      adMobBanner.rootViewController = self
      adMobBanner.loadRequest(GADRequest())
    }

    コードから作る場合

    上記コードを以下のように置き換える。
    //スマートバナーにしておけば画面横幅に(だいたい)合わせてくれる
    adMobBanner = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait)
    //広告ユニットID
    adMobBanner.adUnitID = "ca-app-pub-xxxxxxxxxxxxxxxxx/xxxxxxxxxx"
    //ルートのViewControllerを指定。だいたい self でいいのでは。
    adMobBanner.rootViewController = self;
    //バナーの位置を画面サイズと自分の大きさから決定(画面下に貼る場合)
    adMobBanner.frame = CGRectMake(CGRectGetMidX(view.frame) - adMobBanner.frame.size.width / 2, CGRectGetMaxY(view.frame) - adMobBanner.frame.size.height, adMobBanner.frame.size.width, adMobBanner.frame.size.height) //中央に配置
    //viewに追加
    view.addSubview(adMobBanner)
    adMobBanner.delegate = self //Delegateの設定
    //広告を読み込んで表示させる
    adMobBanner.loadRequest(GADRequest())

    上記コードの3カ所を変更する。

    1. 上記コード中のadUnitID(ca-app-pub-xxxxxxxxxxxxxxxxx/xxxxxxxxxxの部分)を、広告ユニットを作った際に表示された広告ユニットIDに置き換える。
      広告ユニットID
    2. バナーを表示するためのルートのViewControllerを指定する。このViewControllerは広告がクリックされたときに重ねて表示される際に使われる。とりあえず self でいんじゃね?
    3. GADBannerViewのloadRequest関数をGADRequest()オブジェクトでコール。これで広告が読み込まれ、表示される。

    Delegateの設定

    iAd同様、広告が表示できたりできなかったりの時に呼ばれるDelegate関数がいくつかある。

    当然、クラス先頭でDelegateの宣言をする。
    class ViewController: UIViewController, GADBannerViewDelegate { … }

    関数名はadView〜で始まるので、入力すると補完表示してくれるのでそれで調べて。

    //Delegate関数
    func adViewDidReceiveAd(bannerView: GADBannerView!) {
        print("AdMob表示できた😄")
    }
      
    func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
        print("AdMob表示できず🤔\(error)")
    }

    didFailToReceiveAdWithErrorの方は表示失敗時だと思うんだが、表示失敗しなくても(この関数が呼ばれなくても)広告が表示されない場合があるようだ。この辺はよくわからん。

    テスト用広告の設定

    開発中に、誤タップや表示回数の統計に影響しないよう、本物の広告のかわりにテスト用広告を表示するように指示されている。
    そのためにiOSシミュレータもしくは実機のテストデバイスIDを設定する必要がある。

    シミュレータはすでにAdMobの方で定数kGADSimulatorIDとして宣言されてるのでそれを使う。

    実機の方はデバイスごとに違うので、一度実機でAdMobを表示させた場合、Xcodeの下部のメッセージ欄に表示される以下のようなメッセージの「xxxxxxxxxxxxxxxxxxxxxxxxxxx」の部分を使う。

    2016-06-28 00:29:04.837 alien[8831:7496717] <Google> To get test ads on this device, call: request.testDevices = @[ @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ];
    前述したコードの
    //広告を読み込んで表示させる
    adMobBanner.loadRequest(GADRequest())
    の部分を以下に置き換えればいい。

    //テスト広告表示用
    let request:GADRequest = GADRequest()
    if TARGET_OS_SIMULATOR == 1 {
        request.testDevices = [kGADSimulatorID] //iOSシミュレータ用
    } else {
        request.testDevices = ["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] //実機用
    }
    //広告を読み込んで表示

    adMobBanner.loadRequest(request)

    要はGADRequestクラスのプロパティを変更し、loadRequestしているわけだ。
    シミュレータと実機のどっちで実行されてるのかは TARGET_OS_SIMULATOR で判定できる。
    (1がシミュレータ、0が実機)
    値はXcodeでシミュレータと実機のどちらを選択しているかで変化するので、Will never executedというWarningが出るけど気にしないでいい。

    リリース時はこのままのコードでかまわない。
    なぜなら、テストデバイスIDが実行デバイスと異なる場合には本物の広告が表示される仕組みだからだ。

    Objective-Cの場合のコード

    Objective-Cで書く場合も参考までにざっと載せとく。
    - (void)adMob
    {
        //いくつかサイズがあるが、スマートバナーにしておけば画面横幅に(だいたい)合わせてくれる
        adMobBanner = [[GADBannerView alloc]initWithAdSize:kGADAdSizeSmartBannerPortrait];
        //広告ユニットIDを指定する
        adMobBanner.adUnitID = @"ca-app-pub-**********************"; //WebAdMobの広告設定時に書かれてたもの
        adMobBanner.rootViewController = self;
        adMobBanner.frame = CGRectMake(CGRectGetMidX(self.view.frame) - adMobBanner.frame.size.width / 2, 0.0,
                                        adMobBanner.frame.size.width, adMobBanner.frame.size.height); //中央に配置
        [self.view addSubview:adMobBanner];
        //広告を読み込んで表示
        GADRequest *request = [GADRequest request];
        //テスト広告の設定
        if (TARGET_OS_SIMULATOR == 1) {
            request.testDevices = @[kGADSimulatorID]; //iOSシミュレータ用
        } else {
            request.testDevices = @[@"******************************"]; //実機用
        }
        [adMobBanner loadRequest:request];
    }

    変なメッセージが出る

    うちでは出なかったんだけど、以下の変なメッセージが出る場合があるようだ。
    This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes.  This will cause an exception in a future release.
    「バックグラウンドのスレッドでオートレイアウトをいじってるようだな? 将来痛い目にあうぞ!」という内容だと思う。
    どうやらViewが確定する前のviewDidLoadメソッドとかでAdMobを初期設定したりすると出るようで。
    以下のようにdispatch_asyncのブロック中に入れておけば大丈夫だそうだ。(以下はObjective-Cのコード)
    dispatch_async(dispatch_get_main_queue(), ^{
        ここにadMob設定コードを書く

    });

    審査提出時の注意

    AdMobはターゲット広告を利用するようなので、iTunesConnectから審査提出時に最後に聞かれる「IDFAを使ってるかどうか」などという項目に必ずチェックを入れること。
    IDFA使ってるのにチェックを入れないと、リジェクトされて新しいバイナリを求められるってさ。
    「下記の目的で…」のチェックは自分の場合、一番上の「App内で広告を出す」だけで良かったみたい。他の項目は何言ってるのかわかんないしね。

    2016年6月24日金曜日

    Gitでバージョン管理

    よくわからんのでまとめとく。
    間違ってたらすまなんだ。

    Gitってなんだ?

    ジットと読み、Linux発でソースコードのバージョンを管理するための仕組み。
    ソースコードの差分、ディレクトリ構造などの変更履歴を取っておくことで、変更前に戻すことができる。
    XcodeではXcode 4から実装している。

    リポジトリ

    ファイルやディレクトリの状態を記録する場所。

    • ローカルリポジトリ
      • 一人で開発してる場合、端末上に作る
      • Xcodeではプロジェクト作成時の保存ダイアログ上で「Create Git repository on My Mac」にチェックを入れることで作る。(デフォルトでチェックされてる)
    • リモートリポジトリ
      • 複数で開発してる場合、サーバ上に作る
      • Xcodeでの作り方はよくわかんないんで略

    コミット

    リポジトリに変更履歴を記録すること。
    1の次に2、2の次に3といった形で順番に記録される。
    XcodeではメニューのSource Control/Commit...。
    ソースファイル名の横にMとかAとか付いてるのがコミット可能なファイル。
    Commitの画面で、どこをどう直したかなど、コメント入力必須。

    ブランチ

    大きな変更がある際など、コミットの流れを分岐させること。
    3でブランチした場合、3’の流れが新たに作られ、3’を4’に変更しても、3の流れの方は影響を受けない。
    分岐させたブランチはマージ(merge/合流)させることができる。
    最初のコミットで作られるのがマスター( master)というブランチ。この例で言えば「’」のつかない1〜3の流れ。

    チェックアウト

    今いるブランチを出て、別のブランチに移ること。

    プッシュ/プル

    • プッシュ
      • リモートリポジトリに対して変更を書き込む
      • XcodeではSource Control/Push...
    • プル
      • リモーとリポジトリから変更を読み込む
      • XcodeではSource Control/Pull...
    リモートリポジトリについてはよくわかんないので略。

    2016年6月14日火曜日

    アプリリリース方法

    前にもどっかにまとめたはずなんだけど見つかんないし、iTunesConnectやXcodeのデザインも変わってると思うので、あらためて簡単に。
    細かいところがちょこちょこ変わるので、2016年12月現在の方法に更新しました。

    新規App

    iTunesConnectにログインし、新規App登録を開始する。
    2016年12月現在
    • 名前
      • アプリ名です。
    • プライマリ言語
      • 他言語対応の場合、Englishにしといた方がいいらしい。
    • バンドルID
      • これはXcodeで設定したのを見て入れること。→ 登録ダイアログ中のリンクにあるDeveloper Portal(次項参照)で、事前登録が必要。登録後、プルダウンメニューに表示されるのでそれを選ぶ。
    • SKU
      • 他のアプリとかぶらないものならなんでもいいけど、俺は英文字+通し番号にしてる。

    Developer Portalでの事前登録

    • App ID Description
      • アプリ名を英文字で入れる
    • App ID Prefix
      • チームIDが表示される
    • App ID Suffix
      • Bundle IDにXcodeで設定したBundle Identifier(ドメインを逆さにして入れたアレ)を入れる。間違っちゃダメ。間違うとこの設定はたぶんゴミとして残る。そうなったら無視するしかない。
    上記Prefix、Suffix、アプリ名の順に「.」でつなげたものがApp IDになるらしい。

    • App Services
      • アプリで必要とするサービスがあればチェックする。
      • Apple Pay、HealthKit、iCloud、SiriKitとか、そういうやつね。この項目は後から再編集できる。

    APP STORE情報

    • App情報
      • AppStore上のカテゴリなどを入れる
    • 価格および配信状況
      • AppStoreの価格などの設定
        • 価格をプルダウンメニューから選ぶ
        • 開始日、終了日は最初は変更できないっぽい
      • Volume Purchase Program
        • 教育機関とかがまとめ買いした場合に割り引くかどうか
      • Bitcode自動再コンパイル
        • よくわからんのでデフォルトのままでいいか

    iOS APP

    左側に「1.0 提出準備中」ってなってるのを開くと、スクリーンショットとかの登録ページに移る。
    書いてある内容を読んで必要なものを記入、アップロードしていくこと。

    • バージョン情報
      • App プレビューとスクリーンショット
        • AppStoreで表示する説明画像をiPhoneおよびiPad用を登録する。最も大きい画面サイズのデバイス(iPhoneなら5.5インチのもの)を一種類登録すれば全部のサイズで有効になる。
      • 概要
        • AppStoreでのアプリ説明文
      • キーワード
        • AppStoreでの検索用
      • サポートURL
        • アプリをサポートするためのサイトやSNS
      • マーケティングURL(オプション)
        • なんのこっちゃ?
    • iMessage App
      • 必要な場合だけ
    • Apple Watch
      • 必要な場合だけ
    • ビルド
      • 一番最後にやる。Xcodeからアーカイブしたアプリをアップロードしてからここを設定する(次項参照)
    • App 一般情報
      • App アイコン
        • 1024×1024じゃないとダメ
      • バージョン
        • 1.0からね
      • 年齢制限指定
        • 暴力表現や性的表現があるかなどの項目に答えていく
      • Copyright
        • 著作権表示。テキトーに。
      • 通商代表連絡先情報(韓国App Storeのみなので普通はいらない)
        • 英語で入力。番地は逆さに(山田町1丁目2番地なら1-2 Yamadacho)
        • 電話番号は先頭に国番号を付け、市外局番の頭の0を取ったものにしないといけない。たとえば080-12345678だった場合、+81-80-12345678となる。
      • Routing App Coverage File(オプション)
        • アプリがサポートする地理的領域をファイルで指定だって? 使ったことない。
    • Game Center
      • 必要な場合だけ
    • App Reviewに関する情報
      • 連絡先情報
        • 名前と電話番号とメルアド
          • 電話番号は先頭に国番号を付け、市外局番の頭の0を取ったものにしないといけない。たとえば080-12345678だった場合、+81-80-12345678
      • デモアカウント
        • 審査の時に使う全部の機能が確認できるアカウント情報。デフォルトでチェックされてるから不要なら外す。
      • メモ
        • アプリ審査時に役立つ情報。なければ空欄で。
    • バージョンのリリース
      • 自動でリリースするか、手動でリリースするかなど。普通は自動で。
    並行してXcodeからアップロード作業をする。

    Xcodeでアーカイブとアップロード

    • メニューProduct/Scheme/Edit Scheme...(これいらないかも?)
      • Build ConfigurationをDebug → Releaseに
    • メニューProduct/Archive
      • 右のカラムのValidate...
      • provisioningを選択し、Validate。SuccessfulになったらDone
    • 右のカラムのUpload to App Store...
      • provisioningを再度選択し、Upload
      • これでiTunesConnectにアップロードされる。
      • アップロード後、手直しして再アップの場合、XcodeのGeneral/IdentityのBuildナンバーを変えないとダメ。
      • Upload SuccessfulになったらDone
    数分するとアップロードがiTunesConnectに反映され、iTunesConnectのビルドに出るようになる。
    最近は反映された際にメールで知らせてくれるようだが、なかなか出ない場合はiTunesConnectのページを再読み込みするといいようだ。

    審査提出

    iTunesConnectで必要な項目を全て書き込み、スクリーンショットなどもアップロードしたら、一番上の「審査に提出」。

    最後に、
    • 中で暗号使ってないか?
    • 使ってる画像とかがちゃんと著作権クリアしてるか?
    • ターゲット広告使ってないか?(IDFAとか言うらしい)
      • GoogleのAdMobはターゲット広告なのでここをチェックした
    などと聞いてくるのでそれぞれ答える。

    最近は一両日中に結果を出してくれるなど、かなり早く審査してくれるようだ。

    最後に一言…

    Xcodeから審査提出できるようにせいや!
    いちいちiTunesConnectと行ったり来たりは面倒なんじゃあ!!!
    ああすっきりした。

    すべてのiPhoneに対応させない

    注意:結論から言うと、うまくいきませんでした。

    解像度が多すぎる

    アンドロイドスマホほどじゃないとは思うが、iPhoneは解像度とアスペクト比のバリエーションが多い。
    執筆時現在、以下の画面サイズに対応させなければいけない。
    • RetinaのiPhone4sで640×960
    • 縦にサイズが伸びたiPhone5が640×1136
    • iPhone6では4.7インチで750×1334
    • 最新のiPhone6 Plusでは5.5インチで1242×2208

    このうちiPhone4sだけは縦が短いので、うまく画面を作らないと、それ以外の画面で横がはみ出したり上下に黒い帯を表示させることになってしまう。

    正直、いちいちこんないっぱい対応してられるか! と思う。
    これにiPadの対応までするとなるとますますだ。(iPadはアスペクト比が一緒だからレイアウト変更などは一種類で済むが)
    俺のせこいアプリなんかはiPhone4sの解像度でだけ作って、iPhone6s Plusだろうがスケーリングモードで拡大して表示してくれるとありがたい。
    要はiPhoneのアプリをiPadで使う時みたいに、多少表示が粗く見えても2倍とかに拡大してくれればいいのだ。

    そういう風に作れないだろうか?
    さらに、それでアップルの審査をパスできるだろうか?(最低iPhone5のサイズに対応せんと怒られるのではないか?)

    対応させないためには

    みなさん頑張って各解像度に対応させてるのか、検索してもスケーリングモードで表示させる方法があまり出てこない。
    どうやらアプリ起動時に表示されるLaunch Screen(スプラッシュスクリーンともいうのだな)をどの解像度(機種)の分をインストールするか/しないかで対応解像度を選べるらしい…ということだけ風の便りで聞いていた。


    そこでLaunch ScreenにiPhone4s(3.5インチ)用のLaunchScreenだけ入れiTunesConnectにアップロードし、スクリーンショットも3.5インチ画面のみをアップロードしてみた。
    しかし「審査提出」ボタンを押すと「アプリが他のサイズ用に対応してるから、それ用のスクリーンショットもアップロードしろ」と出てしまった。

    チェックボックス全てOFFにしてみる

    最低限のLaunch Image
    XcodeのLaunchImageの画面でスクリーンショットの入ってない枠が残ってるせいかと思い、LaunchImageのインスペクタでチェックボックスを全てOFFにしてみたが、やっぱりiTunesConnectで同じエラーになる。

    もしかしたらちゃんとしたやり方あるんだろうとは思うけど、近い将来サポートされなくなる3.5インチにこだわって作っててもしょうがないのであきらめることにした。
    あ〜、全部の解像度対応してやりますよ! このヤロー!(TДT)(iPadを除く)

    やっぱりサポートされなくなった

    2016/6/14のアップルのイベントでiOS10について発表があり、iPhone4sが非対応になったようだ。
    これで、若干のアスペクト比の違いはあれど全て縦長になったので(iPadを除く)、デザインはしやすくなったかな。

    iPadのスケーリング表示はどうなる?

    iPadってiPhoneしか対応してないアプリを使う場合、現状ではiPhone4sの解像度をスケーリング表示させてるけど、これからはどうなるんだろうな。
    iPhone5の解像度をスケーリング表示するようになるの?

    iPad対応版を作るんであれば、どのみち今までどおり縦長なiPhone、正方形に近いiPadの両方のデザインを作らないといけませんな。こっちはもう早くからあきらめてる。