だいたいそれでいいんじゃないの

つれつれなるkixixixixiの技術的なストック。http://reload.co.jp

TPKeyboardAvoidingTableViewがiOS8.3 SDKでうごかない

タイトル通り。

反応してくれないくてコードみてたらnotificationの登録が行われていないことがわかる。

TPKeyboardAvoidingTableViewではこのように記述されています。

Apps built using the iOS 8.3 SDK (probably: older SDKs not tested) seem to handle keyboard avoiding automatically. This doesn't seem to be documented anywhere by Apple. Note: this only applies to UITableView.

直訳すると

iOS 8.3 SDKを使用して構築されたアプリはキーボードの処理を自動的に回避するように見えます。

まじかよ。でも #if defined(__IPHONE_8_3)
の分岐を無理やり回避させたら動きました。

なにが正解かわからないのでとりあえず様子してみます。

プロパティのsetter,getter

プロパティのsetter,getterが簡単にできるようなのでいじってみた。

private var _name = ""
var name : String
{
    get
    {
       return _name
    }
    set(newValue)
    {
        _name = "Mr. \(newValue)"
    }
}

こんな感じ。 set(newValue)setに省略できたり。
nameに代入されたときsetがよばれて、nameの値を参照するときにgetがよばれるだけの簡単な仕組み。
これは代入するときに前に"Mr."ってつけてるだけ。 空だったら"noname"と返したり監視することができます。

private var _name = ""
var name : String
{
    get
    {
       return (_name as NSString).length > 0 ? _name : "noname"
    }
    set(newValue)
    {
        _name = "Mr. \(newValue)"
    }
}

また細かく監視するために、代入する直前、直後の処理を走らせることができます。

var name : String
{
    willSet(newValue)
    {
        
    }
    didSet(newValue)
    {
        
    }
}

これを使うとデータの隠蔽やnilへのアクセスを防いだり、データの整形などすごく便利そうですね。
そして書き方がかっこいい。

以上!

やはり俺のAdhoc配信はまちがっている。

f:id:kixixixixi:20150402163146p:plain
続の放映前にぎりぎり間に合いました。

旧Testflight配信がサービス終了して一ヶ月ほど。

クライアントさんにリリース前のチェックをしてもらう際などにiOSアプリのテストではTestflightを利用して配信することが多かった。
それが、TestflightがiTunesConnectに統合されて使い勝手が大きく変わってしまった。

違う点

  • AppleIDに紐付いたユーザに配信する仕組みになった
  • 一度iTCにあげてからの配信なのでBundleIDやBuild Ver.などが一意
  • 1つのAppleID(内部ユーザ)は1つのDeveloperAccountに一意に紐づく
  • 内部ユーザは開発者権限以上が必須
  • 内部ユーザ以外には外部ユーザとして配信(AppleIDはいらないが審査が必要)
  • iTCのUploadとともに配信可能
    など。

細かい修正のたびにビルド番号を変更するくらいなら問題ないけども、外部ユーザに配信するときに審査が必要なことは結構きびしい。
1つのAppleID(内部ユーザ)は1つのDeveloperAccountに一意に紐づく
これが自分的には厳しい。
同時並行で複数アカウントの開発案件等があると案件ごとにAppleIDを作らないと自分ではテストできなくなる。
申請と同じ要領ですぐにテスト配信できるのはすごく楽だけど、内部ユーザごとに配布、非配布を決められないのは困る場合がある。

そんなわけでTestFlightから脱却しようと思いました。
そこで選択肢が3つ
- Deploygate
- Crashlytics
- 自前でつくる

とりあえず、Deploygate使ってみました。
サイトのデザインが綺麗だし、使いやすいしとてもいい。
だけど、同時2つアプリのページしか保持できないのか。あまり同時並行で利用できないか。
有料プランにするならありかな。

Crashlyticsの場合は
Crashlyticsのframeworkをアプリに毎回導入するのはすこし抵抗があったのでやめに。

ということは、自前でつくるしかないよなー。

要件としては - ipaをアップする
- ipaの状態を確認できる
- ipaをwebサイト経由でインストールできる
- 配信ユーザを登録させてインストールページの通知を飛ばす

昔やったときは.plistをつかってitunesのurlscheme踏ませれば配信できたからいけるはす!
想定としてはipaをアップしてplistを解析してbundleIDやUDIDなどを取得して自動的にインストールページが生成できれば簡単にできると思っていた。

ちょっと前にでたLaravel5の勉強も兼ねて黙々と作ってみた。
つまるところがいくつかあった。

最近のXcodeではplistを同時に出力する仕組みがなくなっている。

なのでipaを解凍して Info.plistembedded.mobileprovision の解析を自動化するものをつくるしかない。
Info.plistxmlだから簡単だけども、embedded.mobileprovisionって単純なxmlじゃないんだね。あー。

iOS7の仕様から、配信サーバがhttpsでないとだめになった。

SSL証明書が必要とは。。。

http://marchenterprise.net/2014/03/12/post-211/

こちら大変お世話になりました。

そうこうして

https://deplox.reload.co.jp/

なんとかできました。 通知する部分はできていませんが、人力でipaの個別ページを配信すれば大丈夫。 deviceIDとユーザの紐付けやチームの管理ができてないですが、自分の案件で自分が配信するぶんには十分かなと。

意外にも時間がかかってしまいましたが、技術的には難しくないので全然オレオレTestflightをつくってみるのはありかなと思いました。

以上〜

メジャーアップデートしたLaravel 5を使い始めた話。3

表題の通り。3

1 -> http://kixixixixi.hatenablog.com/entry/20150320/1426836091
2 -> http://kixixixixi.hatenablog.com/entry/20150322/1426957792

実装したら、どこかでミスったらしくエラーに。
エラーのはずなのに画面が真っ白。。。。
.env

APP_DEBUG=true

としてるんだけどなー。 Laravel 4みたいに
f:id:kixixixixi:20150322021615p:plain

みたいな画面が出る想定だったんだけどなんか違う。
デバッグしづれぇ。
logもはいてないし。

どこぞのstockなんとかoverflowphp artisan optimizeしとけといわれた。
http://stackoverflow.com/questions/27192237/laravel-5-env-local-debug-true-no-errors-shown

違う気がしたけどしてみた。

f:id:kixixixixi:20150322022133p:plain
こんな画面がでた。おー!すいません。
理由はわかりません。

画像では内容が違うけど、直せと言われたpermissionを直すとちゃんとエラーログが表示されて保存された。

ということで実装を進めてる。

以上。
多分次あるよ!

メジャーアップデートしたLaravel 5を使い始めた話。2

表題の通り。2

1 -> http://kixixixixi.hatenablog.com/entry/20150320/1426836091

DBつくったからmigrateしよう!とやりました。
ミスったので備忘録。

php artisan make:migration create_table_name

とかってしてmigrationファイル作ってmigrateした。 そのあと、modelをつくった

php artisan make:model ModelName

すると、Modelが/app直下にできてる。/app/modelじゃないんだ!
と思ったらmigrationファイルもできてる!?
謎の二度手間。
便利だけどね。そうならそうと言って欲しかった(どこで

Schema Builderは4と変わりなく、

php artisan migrate

したらmigrateもできました。
makeコマンド便利だ。

php artisan make:controller NameController

でControllerも作れるし!
/app/Http/routes.php

Route::resource('post', 'PostController'); 

と記述すれば、簡単にRESTなControllerの完成!
/post以下にRESTアクセスすればok!

呼ばれる一覧
- /postにGETでアクセス => PostControllerindex()
- /postにPOSTにアクセス => PostControllerstore()
- /post/createにGETでアクセス => PostControllercreate()
- /post/{id}にGETでアクセス => PostControllershow()
- /post/{id}/editにGETでアクセス => PostControlleredit()
- /post/{id}にPUT/PATCHでアクセス => PostControllerupdate()
- /post/{id}にDELETEでアクセス => PostControllerdestroy()

基本的なものは準備されているのが楽だった。
とりあえず、画面遷移させられるね!w

以上!
また次!

メジャーアップデートしたLaravel 5を使い始めた話。

表題の通り。

4で作ったものの改修案件とかあるけど、5が大きく変わったということでずっとLaravel 4を使っていてもだめだなと思い、勉強することに。
簡単に環境構築から。

## インストール php5.4以上とcomposerをインストールした状態で

composer global require "laravel/installer"

laravelコマンドを使えるように。

$HOME/.composer/vendor/bin

のpathも通しておく。

すると

laravel new project-name

project-nameのディレクトリにLaravelが入る。

## 設定もろもろ
document root を project-name/publicにして
例のごとく、

chmod -R 777 storage

すると、laravelのサンプルページがみれました!
.envに設定がいろいろ書いてあるので、dbとかの設定をいじる。
config/app.phpでtimezoneとか修正とかしてとりあえずの設定が終わり。

## ディレクトリ構造すごい変わってる!
viewはresourcesの中で、routeとControllerはapp/Httpの中に。 modelなくなってる。

以上。
続きは次に。


2 -> http://kixixixixi.hatenablog.com/entry/20150322/1426957792

[swift] UIViewのsubclassでのinitの挙動

UIViewのサブクラスを作ったときにinitでの挙動がどうなっているのかなーって疑問になったので自分のまとめ載せておきます。

init()自体をoverrideして初期化時の処理を追加したいときにかくべきなのはinit()なのかinit(fram:)なのか。
とりあえず、下記の挙動でうごきました。

    override init()
    {
        super.init()
    }
    
    override init(frame: CGRect)
    {
        super.init(frame: frame)
    }

    required init(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
    }

コードのみで生成しているのですが、3つともないと落ちます。

調べてみると、override init()override init(frame: CGRect)がコードで生成した時に、 required init(coder aDecoder: NSCoder)がxibなどでつくったときに呼ばれるみたい。

それじゃコードで読んだときどの順番でよばれるのか?と思って調べてみました。

    var i = 0
    
    override init()
    {
        super.init()
        i++
        NSLog("init() cnt:%d", i)
    }
    
    override init(frame: CGRect)
    {
        super.init(frame: frame)
        i++
        NSLog("init(frame:) cnt:%d", i)
    }

    required init(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
        i++
        NSLog("init(code):0 cnt:%d", i)
    }

こんなクラスを作って呼んでみると

  • subView.init(frame:rect)の場合
init(frame:) cnt:1
  • subView.init()の場合
init(frame:) cnt:1
init() cnt:2

おおおおお!init(frame:)は絶対先に呼ばれるのか!
というわけでひとまずはinit(frame:)に処理を書けばいいみたい。

xibをつかったときの挙動とかはまたあとで。

以上!