iOS 開発メモ (2013年3〜4月)

いろいろ開発中に調べたことのメモ

 

・ステータスバーを隠す

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:NO];
self.wantsFullScreenLayout = YES;

 

 ・親のインスタンスにイベントを送りたい

Protocol – Delegateパターンで実装する。

[iOS] Protocol – Delegateパターン | Objective-C イベント伝達 その1 « きんくまデザイン

 

・ARCを有効にしている場合に起こりがちなエラー

(nonatomic, assign) のあたりでエラーが出たら、 (nonatomic, strong) に書き換える。

[ARC][Xcode 4.3] プロパティのデフォルト属性が変更に! – iOS 開発ブログ Natsu’s note

 

※ ARCはXcode4.3以降(?) iOS5以降(?) で使える、自動メモリ管理です。

iOS 5 公開記念! Objective-Cのメモリ管理の革命、 ARC 超入門(サンプルはgitHubに公開) | Zero4Racer PRO Developer’s Blog

 

・UIWebView内のJavaScriptから、Objective-Cのコードを呼び出す

WebView で Javascript と Objective-C のコードを相互に呼び出す方法 ≫ 【スマホ×HTML5】Web&ハイブリッドアプリ開発者ブログ

 

・CGRectをNSLogで確認

NSLog(@"%@",NSStringFromCGRect(frame));

 

・UIViewのアニメーション

- (void)doAnimation
{
    self.alpha = 0.1f;
    self.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
    [UIView animateWithDuration:0.3f
        animations:^{
            self.alpha = 1.0f;
            self.transform = CGAffineTransformMakeScale(1.2f, 1.2f);
        }
        completion:^(BOOL finished){
        self.transform = CGAffineTransformIdentity;
    }];
}

SimpleBoxes | ブロックを使ったアニメーション処理 (iPhone/iPad, Objective-C 2.0)

 

・UIWebViewのURL取得

NSString* url = [webView stringByEvaluatingJavaScriptFromString:@"document.URL"];

UIWebViewで表示中のURL、titleを取得する: iPhoneアプリ開発備忘録

 

・ファイル名の文字列処理

// ディレクトリ名を取り出し

NSString *directoryPath = [url stringByDeletingLastPathComponent];

// ファイル名を取り出し

NSString *fileName = [url lastPathComponent];

// 拡張子取り出し

NSString *extension = [fileNameWithExtention pathExtension];

// 拡張子無しのファイル名

NSString *fileNameWithoutExtension = [fileName stringByDeletingPathExtension];

iPhone War Room: How to load local HTML resouces in UIWebView
iPhoneアプリ開発と留学 : ファイルパスからファイル名や拡張子などのみを取り出す

 

・文字列の結合

NSString *s1 = @"Hello";
NSString *s2 = @"World";
NSString *str = [NSString stringWithFormat:@"%@ %@",s1,s2];

 

・文字列のSplit

NSString *string = @"hoge,moge,fugo,mogo";
NSArray *names = [string componentsSeparatedByString:@","];
NSLog(@"%@",names);

My Codex Leicester » Blog Archive » NSStringを特定文字で分割する – Mac/iOS の Audio Visual Programmingの話題

 

・文字列の一致の比較

if ([str3 isEqualToString:str4]){
}else{
}

Compare NSString Objects (Updated)

 

・配列内のindexOf

[配列 IndexOfObject:要素]

 

・配列の要素削除

[配列 removeObjectAtIndex:インデックス];

Objective-CのTips – メメメモモ

 

・AS3のDictionary的なもの

NSMutableDictionary

配列とループ処理を理解しよう – @IT

 

・addSubViewの反対

removeFromSuperview

【コラム】ダイナミックObjective-C (73) デザインパターンをObjective-Cで – Composite (2) | 開発・SE | マイナビニュース

 

・UIWebViewのガベコレ強制発動

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];

iPhoneアプリでHTTP通信を頻繁に行っているとメモリ使用量が…

Cocoaの日々: [iOS] UIWebView のキャッシュ調査

(旧) Cocoaの日々: WebKit検証(36) – キャッシュをクリアする(成功)

 

iOSアプリ実機検証 〜 TestFlight配布

定期的に訪れる、iOS勉強作業。

========
実機検証
========

▼証明書の作成

キーチェーンアクセス > 証明書アシスタント > 認証局に証明書を要求

ユーザーのメールアドレス: メアドを入力
通称: 自分の名前など
CAのメールアドレス: 空欄で良い
要求の処理: ディスクに保存、鍵ペア情報を指定にチェック

鍵のサイズ: 2048ビット
アルゴリズム: RSA

 

iPhone Provisionning Protal > Certificates

で Certificate を作成してダウンロード。

キーチェーンアクセスの「ログイン」という項目内にドロップして追加。

(Development, Distributionどちらも)

 

App IDの作成

Bundle Identifierは自分のドメインなどに紐付けて、最後は 「 * 」 。
例) net.soohei.*

 

Deviceの追加

UDIDを入力してデバイスを追加する。Xcodeのオーガナイザーからも出来る。

 

Provisioning Profileの作成 (Development, Distributionどちらも)

Certificate、App ID、Device を指定して Provisioning Profile をつくる。

ダウンロードしてXcodeに登録

 

▼ アプリのビルド、実機転送

Build Settings の中の Code Signing で、
Debug にDevelopment用のプロファイル、
Release にDistribution用のプロファイルを指定してビルドする。

sign関係のエラーが出たら、証明書や鍵が正しくマシンに入っているか確認。

アプリを Run する時に、Simulatorを選ぶと、Mac上でシミュレーターが起動、
実機を選ぶと、実機で確認できる。

実機がプロファイル内にデバイスとして登録されているかを再確認。
転送に失敗した場合は、実機にプロファイルが入っているか、

 

 

========
TestFlight
========

Adhoc用のアプリを、インターネット経由で配布・インストールできる便利なサービス。
> Test Flight

 

▼ アプリのインストールに必要な条件

・TestFlight のアカウントを持ってること

・自分の端末(デバイス)の UDID が TestFlight のアカウントに紐付いていること
(端末からTestFlightサイトにアクセスすると簡単に登録できる)

・アプリのプロファイルが端末内にインストールされていること
(TestFlightのアプリ配布用URLからもインストールできる)

・配布されたアプリのプロファイル内に、自分の端末が登録されていること

 

▼ アプリの配布に必要なもの

・TestFlight のアカウント

・Distribution (adhoc) 用のプロファイルがマシンに入っていること

・同プロファイルを使ってビルドされたアプリのIPAファイル (Xcodeで Product > Archive)

 

▼ 配布手順

・Provisioning Portal の Devices にデバイスのUDIDを登録 (Xcodeのオーガナイザー経由でも良い)

・Distribution用の Provisioning Profile で、デバイスを登録

・アプリをビルドしてIPAファイルをつくる (Xcodeで Product > Archive)

・IPAファイルを TestFlightのApp 経由で配布・通知

 

▼ もし配布する端末を増やしたくなったら

・TestFlight のアカウントにデバイスの UDID を登録。

・Provisioning Portal で Devices にデバイスを追加

Provisioning Profile (Distribution) を再ダウンロード

・アプリを再ビルド、再配布

・通知を受け取った端末から、TestFlightのURLにアクセスしてアプリをダウンロードする。

 

or もっと便利な方法教えてもらいました!

 

・TestFlightのweb上で、Apps → アプリ選択 → Permissionos → Updated Provisioning Profile の Update Profile からプロファイルを再ダウンロード。

・Teammates In The Provisioning Profile に新しいメンバーが現れたら、チェックボックスをON。

・Just Update か、Update & Notify する。

・通知を受け取った端末から (Just Updateだと通知はこない)、TestFlight サイトにアクセスしてアプリをダウンロードする。

 

再ビルドの手間がないのがGood!

 

参考:
iPhoneアプリの配布用(Distribution)のビルドを行う – Cyber Passion for iOS
2台目のMacのXcode:「Valid signing identity not found」 | MUSHIKAGO APPS MEMO
Problem while trying to set up distribution profile
TestFlight とりあえずどんなものか | MUSHIKAGO APPS MEMO
TestFlightの使い方と導入方法 | Technology-Gym

MacPortとRVMをやめて、Homebrewとrbenvにする

http://ikeay.net/182によくまとまってます。えらい。

 

▼ MacPortのアンインストール

MacPortのアンインストール

$ sudo port -fp uninstall installed

sudo rm -rf
/opt/local
/Applications/DarwinPorts
/Applications/MacPorts
/Library/LaunchDaemons/org.macports.*
/Library/Receipts/DarwinPorts*.pkg
/Library/Receipts/MacPorts*.pkg
/Library/StartupItems/DarwinPortsStartup
/Library/Tcl/darwinports1.0
/Library/Tcl/macports1.0
~/.macports

参考: Chapter 2. Installing MacPorts | 2.5. Uninstall

 

▼ RVMのアンインストール

$ rvm seppuku
$ rm -rf ~/.rvm

.bash_profile
.bashrc
.zprofile
の中から、MacPortsっぽい記述、RVMっぽい記述は削除

 

▼ rbenvのインストール

$ brew install openssl

※ openssl.orgが落ちている時は…
FIX: Error: Download failed: http://openssl.org/source/openssl…

$ brew install readline

$ brew link openssl
$ brew link readline

$ brew install rbenv
$ brew install ruby-build

.bashrc, .bash_profileに

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

を追加。

.zprofileに

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init - zsh)"

を追加。(引数にzshって入ってます!)

参考: Learn Ruby – Install – kidomahの日記

 

ruby -v

して、指定したrubyのバージョンが出ればOK。

 

▼ rbenvを使う

$ rbenv install 1.9.3-p392
$ rbenv global 1.9.3-p392

 

▼ bundlerとか (13/4/17 追記)

$ rbenv rehash
$ gem install bundler
$ rbenv rehash

$ which gem
$ which bundle

これでbundlerがちゃんとrbenv環境に向いているか確認。

rvmからrbenvへ移行したらbundle installに失敗した。 #Ruby #bundler – Qiita [キータ]


その他のコマンド

・インストールできるもの一覧

$ rbenv install --list

・インストールしているバージョン一覧

$ rbenv versions

・今使ってるバージョン

$ rbenv version

・(****は任意のバージョン)デフォルトのバージョンを指定

$ rbenv global ******

・インストールしたrubyやgemのパスを通す

$ rbenv rehash

参考: Rubyのバージョン管理システムをrbenvにした

coffeescriptでprivate

あらためて復習。
CoffeeScriptのクラスではprivateな変数・関数はつくれないっぽい。
(継承のオーバーライドを想定しない場合は、できないことはないっぽい →参考欄の1つ目)
最初に比較用のASのコードを載せています。

 

– AS脳で理解するための比較用 ActionScript
→ private var, private function がcoffeeだと使えない

 

package{
class SampleClass{
public static var staticVar:String = "staticVar";
public static var staticVar2:String = "staticVar2";

private static var _staticVar3:String = "_staticVar3";

public var publicVar2:String= "publicVar2";

/* CONSTRUCTOR */
function SampleClass(){
// インスタンスのプロパティ
this.publicVar = "publicVar";
}

// PUBLIC STATIC FUNCTION
public static staticPublicFunction(){
trace("\n**** from staticPublicFunction");
trace(this);
trace(_staticVar3);
trace(SampleClass.staticVar);
trace(publicVar);
trace(publicVar2);
}

/* PRIVATE FUNCTION */
private function _privateFunction(){
trace("\n**** from _privateFunction");
trace(this);
trace(_staticVar3);
trace(SampleClass.staticVar);
trace(publicVar);
trace(publicVar2);
}

// PUBLIC FUNCTION
public function publicFunction(){
trace("\n**** from publicFunction");
trace(this);
trace(_staticVar3);
trace(SampleClass.staticVar);
trace(publicVar);
trace(publicVar2);
}

public function callPrivateFunction(){
_privateFunction();
}

public function updateStaticVar3(){
_staticVar3 = "_staticVar3:changed";
}
}
}

 

– CoffeeScript

 

class SampleClass

### PUBLIC STATIC VAR ###
@staticVar: '@staticVar'
@staticVar2 = '@staticVar2'

###
# PRIVATE STATIC VAR
# クロージャー内の変数扱い? インスタンスの変数ではない
###
_staticVar3 = '_staticVar3'

### PUBLIC INSTANCE VAR ###
publicVar2: 'publicVar2'

###
# ここまでのまとめ:
# ・頭に@がつく場合
# 無条件で静的なプロパティになる
# ・@がない場合
# =を使うと静的なプロパティに、
# :を使うとインスタンス(prototype)のプロパティになる
###

### CONSTRUCTOR ###
constructor: ->
# インスタンスのプロパティ
@publicVar = '@publicVar'

### PUBLIC STATIC FUNCTION ###
@staticPublicFunction = ->
console.log('\n**** from staticPublicFunction')
console.log(@)
console.log _staticVar3 #OK
console.log SampleClass.staticVar #OK
console.log @publicVar #NG
console.log @publicVar2 #NG
@

###
# PRIVATE FUNCTION の出来損ない
# インスタンスのメンバー変数にアクセスできない!
# クロージャー内の関数扱い?
###
_privateFunction = ->
console.log('\n**** from _privateFunction')
console.log(@)
console.log _staticVar3 #OK
console.log SampleClass.staticVar #OK
console.log @publicVar #NG
console.log @publicVar2 #NG
@

### PUBLIC FUNCTION ###
publicFunction: ->
console.log('\n**** from publicFunction')
console.log(@)
console.log _staticVar3 #OK
console.log SampleClass.staticVar #OK
console.log @publicVar #OK
console.log @publicVar2 #OK
@

callPrivateFunction: ->
_privateFunction()
@

updateStaticVar3: ->
_staticVar3 = '_staticVar3:changed'
@

### 1つ目のインスタンス sample をつくって色々テスト ###

sample = new SampleClass()
console.log('\n**** from global')
console.log SampleClass.staticVar #OK
console.log sample.publicVar #OK
console.log sample.publicVar2 #OK
console.log sample._staticVar3 #NG

sample.publicFunction()
sample.callPrivateFunction()
SampleClass.staticPublicFunction()

### _staticVar3を更新する ###
sample.updateStaticVar3()

### 2つ目のインスタンス sample2 をつくって色々テスト ###
console.log '\n#### sample2 ####'

sample2 = new SampleClass()
console.log('\n**** from global')
console.log SampleClass.staticVar
console.log sample2.publicVar
console.log sample2.publicVar2
console.log sample2._staticVar3

sample2.publicFunction()
sample2.callPrivateFunction()
SampleClass.staticPublicFunction()

###
# sample2をつくっての実験のまとめ:
# _staticVar3 が変わってしまっていることからも、
# インスタンス変数ではなく、スタティックな変数であることがわかる。
###

 

– コンパイル結果 JavaScript

 

// Generated by CoffeeScript 1.4.0
(function() {
var SampleClass, sample, sample2;

SampleClass = (function() {
/* PUBLIC STATIC VAR
*/

var _privateFunction, _staticVar3;

SampleClass.staticVar = '@staticVar';

SampleClass.staticVar2 = '@staticVar2';

/*
# PRIVATE STATIC VAR
# クロージャー内の変数扱い? インスタンスの変数ではない
*/

_staticVar3 = '_staticVar3';

/* PUBLIC INSTANCE VAR
*/

SampleClass.prototype.publicVar2 = 'publicVar2';

/*
# ここまでのまとめ:
# ・頭に@がつく場合
# 無条件で静的なプロパティになる
# ・@がない場合
# =を使うと静的なプロパティに、
# :を使うとインスタンス(prototype)のプロパティになる
*/

/* CONSTRUCTOR
*/

function SampleClass() {
this.publicVar = '@publicVar';
}

/* PUBLIC STATIC FUNCTION
*/

SampleClass.staticPublicFunction = function() {
console.log('\n**** from staticPublicFunction');
console.log(this);
console.log(_staticVar3);
console.log(SampleClass.staticVar);
console.log(this.publicVar);
console.log(this.publicVar2);
return this;
};

/*
# PRIVATE FUNCTION の出来損ない
# インスタンスのメンバー変数にアクセスできない!
# クロージャー内の関数扱い?
*/

_privateFunction = function() {
console.log('\n**** from _privateFunction');
console.log(this);
console.log(_staticVar3);
console.log(SampleClass.staticVar);
console.log(this.publicVar);
console.log(this.publicVar2);
return this;
};

/* PUBLIC FUNCTION
*/

SampleClass.prototype.publicFunction = function() {
console.log('\n**** from publicFunction');
console.log(this);
console.log(_staticVar3);
console.log(SampleClass.staticVar);
console.log(this.publicVar);
console.log(this.publicVar2);
return this;
};

SampleClass.prototype.callPrivateFunction = function() {
_privateFunction();
return this;
};

SampleClass.prototype.updateStaticVar3 = function() {
_staticVar3 = '_staticVar3:changed';
return this;
};

return SampleClass;

})();

/* 1つ目のインスタンス sample をつくって色々テスト
*/

sample = new SampleClass();

console.log('\n**** from global');

console.log(SampleClass.staticVar);

console.log(sample.publicVar);

console.log(sample.publicVar2);

console.log(sample._staticVar3);

sample.publicFunction();

sample.callPrivateFunction();

SampleClass.staticPublicFunction();

/* _staticVar3を更新する
*/

sample.updateStaticVar3();

/* 2つ目のインスタンス sample2 をつくって色々テスト
*/

console.log('\n#### sample2 ####');

sample2 = new SampleClass();

console.log('\n**** from global');

console.log(SampleClass.staticVar);

console.log(sample2.publicVar);

console.log(sample2.publicVar2);

console.log(sample2._staticVar3);

sample2.publicFunction();

sample2.callPrivateFunction();

SampleClass.staticPublicFunction();

/*
# sample2をつくっての実験のまとめ:
# _staticVar3 が変わってしまっていることからも、
# インスタンス変数ではなく、スタティックな変数であることがわかる。
*/

}).call(this);


参考:
CoffeeScriptでstatic/private/publicなメンバ/メソッドをもったクラスのつくりかた « DevJamMemo
[改訂]CoffeeScriptでstatic/private/publicなメンバ/メソッドをもったクラスのつくりかた « DevJamMemo
JavaScriptでstatic/private/publicなメンバ/メソッドをもったクラスのつくりかた | ALUMICAN.NET
JavaScript のスコープチェーンとクロージャを理解する – tacamy memo
AcrionScript3やってた自分からみたCoffeeScript | 宇都宮ウエブ制作所

アルミ缶先生さすがっす