2016年5月19日木曜日

iAd廃止だってね

2016年6月30日でiAdと関連広告サービスが廃止されるという英文メールがアップルから届いた。
薄々は聞いてたけど、書かれてるように「すでにご存知と思いますが」ってことはなかったぞ。

うちのアプリ、たしかiAd表示できない時はGoogleのAdMobも使うようにはしてるけど、全部対応させてたかしら?

アップルはあんまり儲からなかったんだろうね。もうちょっといろんな表示に対応したりして他の広告サービスを凌駕すればよかったのに。
あとiPadでiPhone用アプリを表示した時にiAdが表示されないとか不具合もあったのが痛い。少なくともうちの環境では表示されなかった。

広告サービスの規約が厳しくなったりしてるようだし、あんまり広告表示させたくないのかも。
本当は無料アプリに広告のパターンじゃなくて、百円でもいいからお金を払ってもらう方が健全だと思うんだけどね。

なお、iAd廃止直前の6月23日にiAd付で審査提出したアプリが、翌日無事に審査通過してリリースされた。
ギリギリまで受理してくれるんだね。

2016年3月29日火曜日

アプリ名のローカライズ

日本語のアプリ名の付け方。

1 XcodeのPROJECT/Info/LocalizationにJapaneseを追加

Storyboardなんかのローカリゼーションファイルを作るというダイアログが出るので、作ってやる。

2 InfoPlist.stringsというファイルを作る

 Supporting Filesの中に新たなInfoPlist.stringsというファイルを作る。(ファイルの種類はiOS/ResourceにあるStrings File)
右側のインスペクタのLocalizeボタンを押して、種類でJapaneseを選ぶ。

InfoPlist.stringsの中に
CFBundleDisplayName = "(日本語アプリ名)";
とやれば完成。
実機でコンパイルすればアプリ名が設定した日本語名になってるよ。

2016年3月25日金曜日

Xcode7.3、Swift2.2の変更点

iOS9.4、OSX 10.11.4などのリリースにより、Xcodeが7.3、Swiftが2.2になり、仕様変更があった。プロジェクトを開いたら、いっぱいWarningが出たよ。
まあほとんど自動的に修正してくれるようだが。
今はまだ非推奨(deprecated)の段階なので、そのままでもコンパイルしてくれる。

まずソフトウェアアップデートで表示された変更点を和訳。

Xcode 7.3の変更点


  • XcodeのiOSとOS Xのplaygroundは、対話的で、ユーザー生成のイベント(例えばボタン・クリックとiOSジェスチャー)に反応します。
  • コード補完機能は、より知的な提案(APIの範囲内で単語の最初の文字に基づいたオプションを含む)を提供します。
  • デバイスウィンドウは、一つのiPhoneに対して複数のApple Watchデバイスの間での切り替えをサポートします。
  • SwiftとObjective-C両方の記述を評価するとき、デバッガーは必要なフレームワークを自動的にインポートします。
  • ビューデバッギングは、さらなるインスペクター情報、コンテキストメニューとアシスタントエディター・オプションを追加します。
  • 静的アナライザーは、nullabilityとObjective-Cの属性に関連した、より潜在的問題を確認します。

Swift2.2の変更点


  • Swift.orgからダウンロードされるSwift toolchainsは、プリファレンスのupdated Componentsタブから簡単に選択できます。
  • 新しく#file、#line、#columnと#functionの記述を追加。
  • スライスタイプの新しいremoveFirst()とremoveLast()メソッドを含む、標準ライブラリの改善。
  • 条件付きビルドのオプションは、現在のSwiftバージョンに基づく同じファイルの範囲内で、はっきりしたコードブロックを編集することができます。
  • メソッドのObjective-C selectorを参照する、新しい#selector記述。
  • 失敗可能なクラス・イニシャライザは、スーパークラスのイニシャライザを呼ぶ前に、「nil」を返すことができます。
  • 改善されたコンパイル時診断メッセージ。
  • 例えば++、--文と、C言語スタイルのループ文を、将来リリースされるSwift 3に備えて非推奨化。
よくわかんないのもあるけど、まあいいや。
次に、自分のプロジェクトで引っかかった点のまとめ。

selectorの記述で、Objective-C式が非推奨になる

finishTimer = NSTimer.scheduledTimerWithTimeInterval(rnd,
                target: self,
                selector: "finish",
                userInfo: nil,
                repeats: false)

新(Flatwoodsはコードが書かれたクラス名)
finishTimer = NSTimer.scheduledTimerWithTimeInterval(rnd,
                target: self,
                selector: #selector(Flatwoods.finish),
                userInfo: nil,
                repeats: false)


ちゃんとクラス名も入れろってことか。

加算、減算演算子の++、--が次期Swift3から使用不可に


actionCounter++



actionCounter += 1

for文も変わった


for (var i = 0; i < 10; i++) {
    print(i)
}

for i in 0..<10 {
    print(i)
}

旧のi++が将来的に使えなくなるとしてWarningが出るのは当然として、C言語形式の書き方も将来的に廃止になるからとしてfor in形式に書き換えさせられる。

2015年12月17日木曜日

画面遷移時のトランジションエフェクトで変なメッセージ出る

別画面をトランジションエフェクト付きで開こうと、次のコードを実行したら、毎度変なメッセージが出ちゃうですよ。
一応トランジションは実施される。(遷移前のviewの透明部分に先に遷移後のviewの画像が出ちゃうとか細かい不具合は見られるけど)

alienVC.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
self.presentViewController(alienVC , animated: true, completion: nil)

遷移先の画面で
self.dismissViewControllerAnimated(true, completion: nil)
ってやって前の画面に戻る時にも同じメッセージが。

毎度出るメッセージ<_UIFlippingLayer: 0x14cf13c90> - changing property magnificationFilter in transform-only layer, will have no effect

和訳すると、
「トランスフォーム専用のレイヤーで拡大フィルターのプロパティーを変更しました。エフェクトできません」
とかそんな感じか?

これ、上みたいにコードで開く場合だけじゃなく、Segueで開く/戻る時にも出るんだよね。
UIFlippingLayerについてのメッセージだから、FlipHorizontalのエフェクトが関係するんだろうね?
UIModalTransitionStyle.FlipHorizontal.CrossDissolveにすると出ない。
海外のサイト見たら、CATransformLayerでも同様のメッセージが出てるようで、「無視することがオススメ」なんて回答されてることも。
うざいっちゃうざいけど、よくわかんないし、大きな実害も出てないから当面無視するしかないか。

2015年11月19日木曜日

NSUserDefaultsにenumを保存

変数currentStageは、下のように定義されてるenum(列挙型)の値が入ってる。
これをUserDefaultsに保存しようと思ったのだが、直接保存できないようなので調べたよ。

enum stage:String {
    case forest
    case beach
    case room
    case wheatField

}


まずそのまま保存するのはどうにもこうにも無理らしいので、扱いやすいrawValueを以下のように設定してやる。
ここではStringにしてる(使い方によってはIntでもいい)。
そのrawValueをString値(または数値)として保存するわけだ。

enum stage:String {
    case forest = "forest"
    case beach = "beach"
    case room = "room"
    case wheatField = "wheatField"

}

保存時
    func saveData() {
        let ud = NSUserDefaults.standardUserDefaults()
        ud.setObject(currentStage.rawValue, forKey: "currentStage")
    }


読み込んだら今度はそれをenum型に戻すんだけど、これがだいぶ悩んだ。
enum型にはメソッドがあって、rawValueを引数にしてやればいいのだな。
んで、引数の型をas! Stringとして強制的にStringに変換して。
さらにXcode様の指示どおり、最後にも!を付けたよ。
多分これでうまくいってる。

読み込み時
    func loadData() {
        let ud = NSUserDefaults.standardUserDefaults()
        //Stringで保存されたcurrentStageを列挙型stageの値に戻す
        currentStage = stage(rawValue: ud.objectForKey("currentStage") as! String)!
    }


もう21世紀なんだから、言語内で扱える型は全て直接読み書きできるようにすべきだと思うんだけど、どうだろうか?
いちいちこんなことで頭悩ますなんてアホらしいよね。


なお、UserDefaultsにあらかじめデータが入っていない状態で読み出そうとするとnilが返るため、きちんとチェックしておかないと最悪アプリが落ちることになる。
下記のようにif文のオプショナルバインディングというのを使うとコードが少し楽。
ud.objectForKey("currentStage")の結果がnilじゃなかったら値をtestに代入し、nilだった場合はtestにはfalseが入るためにelse文が実行されるというSwiftの仕組み。

        if let test = ud.objectForKey("currentStage") {
            //Stringで保存されたcurrentStageを列挙型stageの値に戻す
            currentStage = stage(rawValue: test as! String)!
            print("保存済み")
        } else {
            print("保存されてない")
        }

Xcode 7でfailed to code signと出た

Xcode 7で、iPadで実機確認しようとしたら、
「failed to code sign」
というダイアログが出てコンパイルできなかった。

なんか
No valid signing identities (i.e. certificate and private key pair) matching the team ID “XXXXXXXX” were found.

Xcode can attempt to fix this issue.
This will reset your code signing and provisioning settings to recommended values and resolve issues with signing identities and provisioning profiles.

The selected team's agent, '俺の名前' must agree to the latest Program License Agreement.  Please visit the Member Center.
https://developer.apple.com/membercenter
とかも出て、要するに自分のteamIDが認証できないらしい。

Fix itとかボタンがあったんで、その通りに押してもダメ。

最後のメッセージを読むに、プログラムライセンスの改定があったから、ブラウザからデベロッパーセンターにアクセスして、agreeしろということのようだ。

そういえば数日前に「Updates for apps on iTunes Connect.」とかいうメールが来てたっけな。
それと関係あるんだろうか。まあいいや。

早速agreeしたが、すぐにはXcodeには反映されないようで、お仲間がいるかどうかググって5分くらいしてから再度試したらうまくいったよ。(直接のお仲間はいなかったみたい)
その際、たしかデベロッパー登録してあるパスワードを入力致しました。

2015年11月16日月曜日

UIButtonの画像のアニメーション

UIImageViewに表示するUIImageはパラパラアニメができるけど、UIButtonに表示する画像もアニメーションができる。
これで、点滅するボタンとかが作れるわけだ。

UIButtonに画像を表示する機能はUIImageViewを使ってるようで、UIButtonのimageViewプロパティにアクセスする。
このプロパティ、リファレンスを読むとreadOnlyってなってるんだけど、さらにその配下にあるanimationImagesなどのプロパティには値をセットすることができる。

やり方はUIImageViewと一緒で、アニメのコマを入れた配列を用意し、animationImagesに設定。
Duration(時間)やRepeatCount(繰り返し回数。0だと無限繰り返し)を設定し、startAnimation()関数で開始する。

唯一注意点はUIButtonのsetImage()関数で、UIButtonに画像を表示する設定にしてやることだ。
通常の、文字だけ表示する設定じゃダメってことね。

        let imageArray:[UIImage] = [
            UIImage(named: "image01")!,
            UIImage(named: "image02")!
        ]
        animeBtn.setImage(imageArray[0], forState: .Normal) //これ必要
        animeBtn.imageView?.animationImages = imageArray
        animeBtn.imageView?.animationDuration = 1.0
        animeBtn.imageView?.animationRepeatCount = 0

        animeBtn.imageView?.startAnimating()