Jun 162014
 

SwiftとObjective-Cの組み合わせ方のまとめ。相互運用では何が出来て何が出来ないのか。Swiftでクラスを記述する際の基礎知識の整理。必要最低限の属性。ゲッターとセッター。プロパティ。初期化と解放。

SwiftとObjective-Cの相互運用

Appleが互換性をもたせ組み合わせて使える言語にした理由は、

  • Objective-Cで、今まで親しんだ手法(言語の挙動や動作の取り扱いができる)をベースに
  • Swiftの持つ、モダンな最新の言語機能を活かしつつ

クラスを記述すること。 前回はSwiftとObjective-Cの互換性やそれぞれから機能をどのように利用するか相互運用について概要を書いたので、パート2は掘り下げて記述する。

 

Objective-Cクラスの継承

  • Objective-Cクラスを継承する場合、コロン(:)を使う
  • Swiftクラス名→コロン→Objective-Cクラス名の順
  • スーパークラスの機能をすべて利用できる
  • 自クラスでメソッドを再定義したい場合はoverrideキーワード
class MyViewController : UIViewController
{
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
    }
}

 


 

プロトコル(protocol)適用

  • カンマ(,)区切りでプロトコルを並べる
  • 複数並べられる
  • スーパークラスの後にカンマしてプロトコルを続ける
  • Swiftでは、クラスやプロトコルのネームスペース(namespace)は統一される
  • Objective-CのNSObjectプロトコルはSwiftではNSObjectProtocolに割り当て

 

class MyViewController : UIViewController, UITableViewDelegate
{
}

 

初期化/解放

  • Swiftでは、クラス中のプロパティを初期化しないまま放置しない
  • Swiftでは、Objective-Cと違い、分割メモリ割当メソッドは存在しない
  • Swiftでは、Objective-Cの初期化メソッドをSwiftに変換するため、Objective-Cクラスを利用してる場合でもSwiftの記法で初期化(initializer)できる
  • Swiftでは、クラスがメモリ解放される前にクリーンナッププロセスを追加する場合はObjective-Cのdeallocメソッドの代わりに解放メソッド(deinitializer/finalizerのようなもの)を実装出来る
  • Swiftでは、インスタントがメモリ解放される前に自動的にこの解放メソッド呼び出される
  • Objective-Cから派生したSwiftクラスを使っている場合、Objective-Cクラスを使っている場合、いずれの場合もSwiftは親クラスの(Objective-Cの)deallocメソッドを呼び出す
class MyView
{
    init(frame : Frame) {

    }
    deinit{

    }
}

 

Interface Builder

  • IBの機能をSwiftのclassから利用出来る属性(attributes)がある
  • アウトレット(@IBOutlet)
  • アクション(@IBAction)
  • ライブレンダリング(@IBDesignable / @IBInspectable)

@IBOutlet

  • プロパティ定義の前に@IBOutlet
  • コレクション(複数)のアウトレットを定義するためにも@IBOutletを利用可能
  • Swiftでアウトレットを定義すると型が割り当てられる(弱参照/オプション/nil)
@IBOutlet var button: UIButton
@IBOutlet var textFields: UITextField[]

@IBAction

  • メソッド定義の前に@IBAction
@IBAction func buttonTapped(AnyObject) {
    println("button tapped!")
}

@IBDesignable

  • InterfaceBuilderの中でインタラクティブにビューのデザインができるようになる。
  • UIViewやNSViewからカスタムなビューを作る場合、クラス定義の前に@IBDesignableを付ける事が出来る。
  • InterfaceBuilderにそのカスタムビューを設置(インスペクタでそのビューのクラスを設定)すると、キャンバスにレンダリングされるようになる。

@IBInspectable

  • プロパティ定義の前に@IBInspectableを付ける
  • ユーザ定義のランタイム属性と互換性がある
  • InterfaceBuilderにカスタムビューを追加すると、インスペクタでプロパティを編集出来る
@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var textColor: UIColor
    @IBInspectable var iconHeight: CGFloat
}

 

 プロパティ属性

参照属性について

  • Swiftではデフォルトは強参照となる
  • オブジェクトへの弱い参照は、弱参照(weak)属性をつかう
class Message
{
    var title : String = "Hello"
}

class Mail
{
    var from : String = "You"
    var to : String = "Me"
    var msg : Message?
    weak var weakmsg : Message?
    init()
    {
        self.msg = Message()
        self.weakmsg = Message() //弱い参照なので保持されない
    }
}

Mail().msg?.title //"Hello"
Mail().weakmsg?.title //nilとなった

読み書き属性について

1)値格納用プロパティ

  • readwrite(読み書き用)には変数(var)属性
  • readonly(書き込み不可)には定数(let)属性をつけて定義
  • readwriteやreadonlyといった属性名は存在しない

varとletを付加するだけ:

    var firstValue: Int
    let length: Int

2)計算結果用プロパティ

  • readwrite(読み書き用)にはgetter/setter両方定義
  • readonly(書き込み不可)にはgetterのみを定義

readwriteの場合(setのパラメータは省略でき、省略時の入力パラメータ名はnewValueが暗黙的に指定される):

var origin = Point() //値格納用途
var size = Size() //値格納用途
var center: Point {
    get {
        let centerX = origin.x + (size.width / 2)
        let centerY = origin.y + (size.height / 2)
        return Point(x: centerX, y: centerY)
    }
    set(newCenter) {//newCenter(Point型)は入力パラメータ
        origin.x = newCenter.x - (size.width / 2)
        origin.y = newCenter.y - (size.height / 2)
    }
}

readonlyの場合(getを省略した形でOK):

    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
    return width * height * depth
    }

コピー

  • Ojbective-Cのcopy属性は@NSCopyingに該当
  • NSCopyingプロトコルに合わせて実装が必要

 

CoreData(@NSManaged)

  • モデル(CoreDataModel)の属性や関連に合わせて、それぞれのプロパティ定義に@NSManagedをつける
  • Objective-Cの@dynamicと同じ
  • @NSManagedは実行時にプロパティの実装が与えられる事を示す
  • @dynamicと違って@NSManagedはCoreDataでのみ利用可能な属性である

 
 
 
 

 Posted by at 17:09
Jun 102014
 

SwiftとObjective-Cの組み合わせ方のまとめ。何が出来て何が出来ないのか。特徴、型、互換性。

SwiftとObjective-Cの言語を利用する側として知っておく事のざっくりまとめ。SwiftからObjective-Cを使う場合、Objective-CからSwiftを使う場合。

Swiftとは?

  • CocoaやObjective-Cと互換性がある
  • SwiftからObjective-CのAPIを呼べる(systemフレームワーク)
  • SwiftからCライブラリを呼べる
  • SwiftからC++を直接呼べない
  • Objective-CからSwiftのAPIを呼べる
  • 拡張子は.swift
  • ヘッダーファイルがない(class記述に全ての情報を含むイメージ)

SwiftとObjective-C互換性

アプリ開発において利点…この互換性が最もフォーカスされるべき箇所。

  • Objective-CのコードからSwiftのクラスを呼べ、SwiftのコードからCocoaのクラスやパターン、書き方ができる
  • アプリ内にSwiftとObjective-Cの言語ファイルが混在していても大丈夫
  • 最新のSwift言語の機能を使うために、Objective-Cで開発したアプリの一部だけでもObjective-Cのコード箇所をSwiftのコードに置き換えることもできる

SwiftからObjective-Cを使う場合

Objective-CフレームワークやCライブラリ(UIKit/Foundation/SpriteKitなど)をimport文でインポート出来、Swiftのコードからモジュール(Module)としてAPI(メソッド/プロパティ/カテゴリ)を利用できる

例えば…

  • idはAnyObjectになる
  • NSStringはStringになる
  • pointerはoptional扱い

初期化プロセス

  • Swiftにはallocは存在しない
  • Swiftにはinitは存在しない
  • Swiftは型はお任せで大丈夫(明示的に指定出来るけれども)

initWith型はinitWith以降を小文字にして第一引数のラベルにするルール

[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]

initWithを消し、Frameをframeにして引数のラベルとして

UITableView(frame: CGRectZero, style: .Grouped)

型は省略できるが明示的に付けることもできる

let table = UITableView(frame: CGRectZero, style: .Grouped)
let table:UITableView = UITableView(frame: CGRectZero, style: .Grouped)

initWithを消し、Frameをframeにして引数のラベルとして

UITableView(frame: CGRectZero, style: .Grouped)

Objective-CのFactory型のメソッドは見やすく便利

[UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0]
UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)

プロパティアクセス

  • ドット構文
  • 括弧は不要
  • Objective-Cではgetterとプロパティは同じ構文だが、Swiftでは全く別物(Objective-C側で@propertyで定義したプロパティのみ、Swiftでプロパティとして扱う)

Objective-Cではプロパティのgetterのように扱っていたものも

[UIColor darkGrayColor]

以下とはならないケースもある、つまりはObjective-Cフレームワーク側で実際は

UIColor.darkGrayColor

@propertyを使わず、単にメソッドとして定義されている場合もあるものはSwiftでは明示的にメソッドとして使い分けてコードを書く。

UIColor.darkGrayColor()

メソッド呼び出し

  • ドット構文
  •  セレクタの最初の箇所がメソッド名
  • 最初の引数を括弧のすぐ内側に記述(引数の名前は不要)
  • それ以降は引数の名前が必要
  • 引数がない場合も括弧は必要

 

[myTableView insertSubview:mySubview atIndex:2];

第一引数は引数の名前は不要、それ以降は必要になる

myTableView.insertSubview(mySubview, atIndex: 2)

 AnyObject(Swift)とid(Objective-C)

  • Swift言語のAnyObjectは様々なオブジェクトを表す型
  • Objective-Cのidと同じ
  • Swiftへインポート(import)する際、id型はAnyObject型にマッピングされる
  • 定数/変数にいずれもどんなクラスのオブジェクトも割当可能
  • 割当時にキャストは不要
  • ただし、オブジェクトに存在しないメソッドを呼ぶと実行時にエラー(実行するまでAnyObjectが何の型か特定されないので安全でないコードになるので注意)
  • エラーを出さないためにSwiftにはいくつかオプションがある

AnyObject型は様々なオブジェクトを受け入れられる

var cell: UITableViewCell = UITableViewCell()
var myObject: AnyObject = UITableViewCell()

キャスト不要

NSDate(myObject).dateByAddingTimeInterval(10)//Swiftでは不要
myObject.dateByAddingTimeInterval(10)

そもそも存在しない場合は実行した時点でエラー発生する可能性あり

myObject.start()

オプション(optinals)

Objective-Cエラーを抑えるSwiftの機能がある

1)?でエラーを回避できる(存在しないメンバーを呼んでる例)

var myObject = NSDate()
let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)

2)if-let構文でメソッド応答の有無の確認ができる

if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found \(fifthCharacter) at index 5")
}

ダウンキャスト(AnyObjectから特定のオブジェクト型へ)

  • キャスト成功する保証はない
  • オプションを戻す可能性がある(nilのようなもの)
  • その値を確認できる

ユーザ設定のロードで日付を取り出す過程…NSDate型か格納されているかは不明

let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefaults.objectForKey("LastRefreshDate")

キャスト成功か値を確認

if let date = lastRefreshDate as? NSDate {
    println("\(date.timeIntervalSinceReferenceDate)")
}

nilじゃないのが確実ならそのまま呼んでも大丈夫

let myDate = lastRefreshDate as NSDate

nilの扱い

  • Swiftでは、全ての値はnilではない
  • ただし、Swiftでは値がない事を示すためにnilを使える
  • 一方、Objective-Cの世界ではnilだったりnilでなかったりする
  • Objective-Cのオブジェクトを利用する前に、nilチェックをすることが確実(値が確実に空じゃないといえる場合を除く)

Extension

  • Objective-Cのcategoryに近い
  • 既存クラス(class)や構造体、列挙体の振る舞いを拡張する
  • カスタム型の拡張が出来る
  • システムフレームワークの拡張が出来る
  • プロパティを追加できる(算術のみ/書換は無理)
  • protocol追加に利用できる
  • Objective-C型のメソッドやプロパティはoverrideできない

拡張方法

  1. モジュールをimportで読み込む
  2. 同じ名前のクラスや構造体、列挙体を参照する
  3. 追加する中身を記述

 

extension CGRect {
    var area: CGFloat {
    return width * height
    }
}

クロージャ(Closures)

  • Objective-CのblockとSwiftではクロージャは互換性がある
  • クロージャと関数は同じ型
  • Objective-Cの__blockがSwiftでは標準的な値の扱われ方となる
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */}
let completionBlock: (NSData, NSError) -> Void = {data, error in /* ... */}

Swiftでのオブジェクト比較

  • ==を使う(オブジェクトの中身の比較)
  • ===を使う(定数/変数が同じインスタンスを参照しているか)

 

 

Objective-CからSwiftを使う場合

SwiftからObjective-Cへのインポートも似たようなイメージ(Swiftで書いたAPIがObjective-Cヘッダとして生成されSwiftモジュールとして利用可能になる)

  • StringはNSStringになるなど上記とは逆方向マッピング
  • 一部はマッピングできないので注意(つまり新言語Swiftのみの進化した言語機能、特徴的な部分は旧言語Objective-Cとは互換がとれないところもある)

 

 Swift言語の型互換性

Objective-Cから派生したSwiftのクラスは自動的に互換性が保たれる(@objcが自動挿入される)が、 Objective-Cから派生してないSwiftのクラスをObjective-Cのコードで利用する場合、@objcを使う必要がある。@objcによりObjective-Cの実行環境でSwiftのAPIが利用できるようになる。

  • Objective-Cから利用したいメソッド、プロパティ、クラスの前に@objc
  • メソッドのシグネチャーが翻訳される(Swift->Obj-Cのケースの逆)
  • @objcをObjective-Cで参照される時の別名定義のために使えるSwiftで書かれたクラス側とクラス名を一致させる時に@objcを使う(Objetive-Cでアーカイブオブジェクト(Archived Objects)を扱っている場合オブジェクト内にクラス名が保存されるため)
@objc(Squirrel)
class りす {
    @objc(initWithName:)
    init (名前: String) { /*...*/ }
    @objc(hideNuts:)
    func 隠す(Int) { /*...*/ }
}

Objective-Cセレクタ

  • Objective-Cのセレクタはメソッド名を参照する型である。
  • SwiftではObjective-Cから派生したクラスの場合、クラス内のメソッドやプロパティはObjective-Cのセレクタとして利用できる
  • SwiftではObjective-Cから派生していないクラスの場合、@objをつける事でセレクタとして利用できる
  • performSelector:メソッドはSwiftには導入されていない

Objective-Cのクラスから派生しているメンバ

import UIKit
class MyViewController: UIViewController {

    func tappedButton(sender: UIButton!) {
        println("tapped button")
    }
}

これはSelector型と同じ。

let mySelector: Selector = "tappedButton:"

 


Optionals

オプション(optional)型は「値が存在しない」ことを表す。Objective-Cにおけるポインタのnilに近い概念だが、クラスではなくすべての型に動作するもの。オプションはObjective-Cのポインタより安全かつ様々な表現を持つ。Swiftの最大の特徴である機能の心臓部に位置する概念。

 

 Posted by at 16:52
Mar 222014
 

64ビット環境ではポインタやスカラ型のバイト長がメモリ使用量を圧迫する。メモリ消費を最適化するには?Appleの開発者資料を整理、図解してまとめる。

NSInteger

Objective-cで頻出するNSIntegerはバイト長、4バイト(32ビット環境)から8バイト(64環境)になる。以下の構造体(struct)は6要素含む。6要素x4=24バイト圧迫するから、6要素x8=48バイト圧迫することになる。

struct date {
    NSInteger second;
    NSInteger minute;
    NSInteger hour;
    NSInteger day;
    NSInteger month;
    NSInteger year;
};

uint32_tは32ビット長つまりは4バイト。当然、こちらがデータサイズは小さい。日付を細かく保持するより、unixtimeのようにある時からの時間を保存し計算や表示の時点で変換して年月日を生成する方法の提案。

struct date {
    uint32_t seconds;
};

Paddingの問題

データ型(type)には決まった長さがある。メモリ上に配置する時にルールがある。揃え(alignment)を行う必要があり、空白(padding)が発生することがある。

ハードウェア視点で解説する。CPUの仕事の一つはメモリから読み込む事。CPUごとにルールがあり、1バイトずつ読む、2バイトずつ読む、4バイトずつ読むというのはCPUの設計に寄るのだ。4つずつ読むルールのCPUに3つずつデータをメモリに置いてもCPUは正しく理解できない。

※この理屈はハードウェアに依存し、ルールが異なるので注意が必要。

charは1バイト、int32_tは4バイト、int_64tは8バイトの長さを持つ。スクリーンショット 2014-03-22 16.30.20

次の構造体は複数のデータ型を持ち、4つの要素をもつ。

struct A {
    char a;
    int32_t b;
    char c;
    int64_t d;
};

これをchar→int32_t→char→int64_tの順に構造体がメモリ空間に配置されれば、以下のように考えられる。 スクリーンショット 2014-03-22 16.30.37

先ほどの通りハードウェアには決まりがある。それにあわせてコンパイラもメモリの内容がCPUに読み込まれ処理されるのが効率的(最小のCPUサイクルで)に行えるように最適化を行う。

スクリーンショット 2014-03-22 16.30.20

  • charは1の倍数ごとに配置
  • int32_tは4の倍数ごとに配置
  • int_64_tは8の倍数ごとに配置

これをもとに、以下のようにグレーの箇所も空白(Padding)として消費される。

スクリーンショット 2014-03-22 16.30.50

このケースではトータルで24bytes消費する。

改良

struct A {
 int64_t d;
 int32_t b;
 char a;
 char c;
};
  • charは1の倍数ごとに配置
  • int32_tは4の倍数ごとに配置
  • int_64_tは8の倍数ごとに配置

のルールをもとにint64_t dから順にchar cまで配置されると次のようになる。結果14バイト。

スクリーンショット 2014-03-22 16.58.25

ポインタの話題

struct node {
    node *previous;
    node *next;
    uint32_t value;
};

このケースではLinkedListの形状。ADGの前後ストーリー関係を表現したり、ダイアログフローの制御に利用できるデータタイプである。この構造体を見ると次の事がわかる。

  • 数値データを1つ含む
  • ポインタを2つ含む
  • uint32_tは4バイト消費する
  • ポインタは構造体のアドレスを参照する
  • 32ビット環境のポインタは4バイト消費(64bit環境では8バイト消費)する

32ビット環境では4バイトx3要素=12バイト消費、から64ビット環境では4バイトの数値要素+8バイトx2ポインタ要素=20バイト消費となる。ポインタ参照のメモリ消費量が2倍になるという点には注意が必要。

以下参照:
https://developer.apple.com/jp/devcenter/ios/library/documentation/CocoaTouch64BitGuide.pdf

 Posted by at 17:24

Objective-Cの整数表現

 プログラミング  Comments Off on Objective-Cの整数表現
Mar 222014
 

Objective-Cでは、整数表現にintやuintやNSUInteger等様々ある。NSString文字変換したり、計算したり、カウントしたりNSArray配列に格納したり様々使い分ける。Objective-Cでのプログラミングには様々な整数表現の違いが出てくる。

Integerとは?
英語の整数の意味。プログラミングでは整数型。 整数とは何か?wikipediaによると、

0 とそれに 1 ずつ加えていって得られる自然数 (1, 2, 3, …) および 1 ずつ引いていって得られる数 (−1, −2, −3, …) の総称である。

http://ja.wikipedia.org/wiki/整数

UIntegerとは符号無し(Unsigned)の整数(Integer)。つまり、Objective-CでのNSUIntegerは正の整数を扱う数である。

符号とは、コンピュータ内部での数値の正負(ゼロより大きいか小さいか)の表現方法…

http://ja.wikipedia.org/wiki/符号付数値表現

NSIntegerかintか?NSUIntegerかuintか?

深い事を抜きにすれば、intはNSIntegerとイコール、uintはNSUIntegerとイコールと使える。
特別な要求が無い限りはNSUInteger/NSIntegerを使うのがベター。具体的な違いは以下のリンク。

http://stackoverflow.com/questions/4445173/when-to-use-nsinteger-vs-int

NSNumberとは?
数を表すオブジェクト型。NSArrayやNSMutableArrayやCoreDataにはプリミティブ型(NSUInteger)を格納できない。 この場合、オブジェクト型(NSNumber)に変換をする。NSArrayでは、格納できるデータはオブジェクト型になる一方、添字となる番号の型はプリミティブ型(NSUInteger)。

定義まとめ
プリミティブ型では*記号無し…

NSInteger num=1;
int num=1;
uint num=1;

オブジェクト型では*記号あり…

NSNumber *num=1;

変換まとめ
プリミティブ型(NSUInteger)→オブジェクト型(NSNumber)

[NSNumber numberWithUnsignedInt:1];

オブジェクト型(NSNumber)→プリミティブ型(NSUInteger)

[NSNumber unsignedIntegerValue]

プリミティブ型(NSUInteger)→オブジェクト型(NSString)

NSString *str = [NSString stringWithFormat:@"%d", 1];

64bit環境への移行

(2014/03追記)
以下、64bit環境に移行する場合のコード記述の注意点。

  • 64ビット long 整数を32ビット整数に代入しない
  • 64ビットポインタを32ビット整数に代入しない
  • 算術演算の際に起こるポインタや long 整数の切り捨て(truncation)(その他、整数型の違いによる算術演算上の問題)を避ける
  •   データ型のバイト長の違いによって起こる、揃え境界(alignment)の問題を解消する。
  • 32ビットランタイム、64ビットランタイムで共通に用いる構造体は、メモリ上の配置が同じであるようにする。
  • アセンブリ言語で記述したコードは、64ビット版の新しい命令コード(opcodes)やランタイムに合わせて書き直す
  •   可変引数の関数を固定引数の関数に(あるいはその逆に)キャストすることは避ける

(下記から一部引用)

https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40013501

https://developer.apple.com/jp/devcenter/ios/library/documentation/CocoaTouch64BitGuide.pdf

 Posted by at 12:16

mediatempleのgridサーバでSVNからweb展開の自動化

 プログラミング  Comments Off on mediatempleのgridサーバでSVNからweb展開の自動化
Jan 292014
 

mediatempleのgridサーバ利用者でSVNにcommitしたときにweb自動展開のscript。svnのpost-commitからwebのdirに自動展開するための初期設定。このscriptはrepositoryの作成、skeletonフォルダ作成、webフォルダ作成、初期checkoutまで一括で行う。

初期Repo作成スクリプト

gitでもなんでもいい。要は用途に合ってる事と使いこなす事。svnは昔からmtサーバに入ってるので活用しやすい。

新規プロジェクト毎に以下のスクリプトを実行するだけでOK。

./create_repo.sh myproject_name

repository作成

99999=site number(mtの仕様)

まず、subversionのレポジトリ作成をし、スケルトンフォルダ作成。

#!/bin/sh
HOME=/home/99999/users/.home/
cd $HOME/data/svn/
svnadmin create --fs-type fsfs $1
svn mkdir file:///home/99999/data/svn/$1/trunk file:///home/99999/data/svn/$1/tags file:///home/99999/data/svn/$1/branches -m 'Create trunk, tags, and branches.'
echo "------------------------------------------";
echo "Repo Created";

post-commitのひな形を作成

自動化するscriptを作成するフロー。プロジェクトごとに展開ドメインを分けたい場合も考慮する。インラインで入力を促してifで振り分け。次のインラインでweb展開先のsub dirを入力する。指定したdirがcommit毎にupdateされる仕組み。

echo "Input type [personal biz] : "
read type

echo '#!/bin/sh' >> conf.tmp
echo 'DOMAINS=/home/99999/users/.home/domains/' >> conf.tmp
echo 'SVN=/usr/bin/svn' >> conf.tmp

if [[ "$type" == "personal" ]]
then

domain="myproj.f60k.com"
echo 'DOMAIN="myproj.f60k.com"' >> conf.tmp

elif [[ "$type" == "biz" ]]
then

domain="forbiz.f60k.com"
echo 'DOMAIN="forbiz.f60k.com"' >> conf.tmp

else

echo "Aborted -> type error!"
rm conf.tmp
exit 1

fi

echo "Input sub dir soon after '/html' [ex.)/subdir/] : "
read dir

echo 'UPDATEPATH=$DOMAINS$DOMAIN/html'$dir >> conf.tmp
echo '$SVN update $UPDATEPATH' >>conf.tmp

post-commit作成を確定

これをpost-commitに書き込む。web展開を望まないなら中止もできる。

echo "------------------------------------------";

cat conf.tmp

echo "------------------------------------------";
echo "Are you OK to write these into a hook script [no=0, yes=1] : "
read ok

if [[ "$ok" -eq 1 ]]
then

mv conf.tmp $1/hooks/post-commit
chmod 755 $1/hooks/post-commit

else

echo "Aborted -> confirmation failed!"
rm conf.tmp
exit 1

fi

初回チェックアウト

svn co file:///home/99999/data/svn/$1/trunk /home/99999/users/.home/domains/$domain/html/$dir

 

Bash全文

以下スクリプト丸ごと。


#!/bin/sh
HOME=/home/99999/users/.home/
cd $HOME/data/svn/
svnadmin create --fs-type fsfs $1
svn mkdir file:///home/99999/data/svn/$1/trunk file:///home/99999/data/svn/$1/tags file:///home/99999/data/svn/$1/branches -m 'Create trunk, tags, and branches.'
echo "------------------------------------------";
echo "Repo Created";

echo "Input type [personal biz] : "
read type

echo '#!/bin/sh' >> conf.tmp
echo 'DOMAINS=/home/99999/users/.home/domains/' >> conf.tmp
echo 'SVN=/usr/bin/svn' >> conf.tmp

if [[ "$type" == "personal" ]]
then

domain="myproj.f60k.com"
echo 'DOMAIN="myproj.f60k.com"' >> conf.tmp

elif [[ "$type" == "biz" ]]
then

domain="forbiz.f60k.com"
echo 'DOMAIN="forbiz.f60k.com"' >> conf.tmp

else

echo "Aborted -> type error!"
rm conf.tmp
exit 1

fi

echo "Input sub dir soon after '/html' [ex.)/subdir/] : "
read dir

echo 'UPDATEPATH=$DOMAINS$DOMAIN/html'$dir >> conf.tmp
echo '$SVN update $UPDATEPATH' >>conf.tmp

echo "------------------------------------------";

cat conf.tmp

echo "------------------------------------------";
echo "Are you OK to write these into a hook script [no=0, yes=1] : "
read ok

if [[ "$ok" -eq 1 ]]
then

mv conf.tmp $1/hooks/post-commit
chmod 755 $1/hooks/post-commit

else

echo "Aborted -> confirmation failed!"
rm conf.tmp
exit 1

fi

svn co file:///home/99999/data/svn/$1/trunk /home/99999/users/.home/domains/$domain/html/$dir

 Posted by at 21:20

Objective-Cでのenumの活用法

 プログラミング  Comments Off on Objective-Cでのenumの活用法
Sep 102013
 

XcodeのObjective-Cで開発している際に使うenumにはNS_ENUMが使える。型の定義を一括で記述できる。NS_OPTIONSを使うとビットマスクの定義が楽になる。

NS_ENUM

NS_ENUM(新しい型を保存する型,新しい型)という使い方。

typedef enum {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};
typedef NSInteger UITableViewCellStyle;

上はNS_ENUMを使うと記述を整理できる。

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

NS_OPTIONS

ビットマスクを列挙して定義したい場合に便利。

NS_OPTIONS(新しい型を保存する型,新しい型)という使い方。

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

参考サイト

http://nshipster.com/ns_enum-ns_options/

http://blog.manbolo.com/2013/08/21/objectivec-coding-style-guide

 Posted by at 15:43

Access-Control-Allow-OriginでJQueryからJSONが読み込めない場合

 プログラミング  Comments Off on Access-Control-Allow-OriginでJQueryからJSONが読み込めない場合
Jul 132013
 

JQueryからJSONを読み込む時にエラーが起きて読み込めない場合の対処法。Access-Control-Allow-Originによるエラーの場合クロスドメインが原因。サーバサイドにヘッダー出力を一つ追加して解決。

JSONをサーバから読み込めない場合の対処法

  • エラーログを出す
  • エラーを特定する
  • Access-Control-Allow-Originの場合は以下の方法で直す

PHPの場合

サーバサイドにヘッダー出力(‘Access-Control-Allow-Origin: *’)を追加。

<?php
header('Access-Control-Allow-Origin: *');
//SQL取得
//json生成
//json出力
echo $json;
?>

異なるドメイン間で読み込もうとするとエラーになる。

url = "http://another.domain/fetch_json.php"
$.getJSON(url, null, (data)=>

	console.log data;

)

参考サイト
http://stackoverflow.com/questions/17160071/xmlhttprequest-cannot-load-is-not-allowed-by-access-control-allow-origin

 Posted by at 12:54

Coffeescriptでクラス毎にファイル分割

 プログラミング  Comments Off on Coffeescriptでクラス毎にファイル分割
Jul 072013
 

Coffeescriptでクラスを書く場合にファイル毎にクラスやモジュールを分ける場合はクラス名にwindowを付けるのが簡単。

coffeescriptのファイル分割

通常はファイル分割すると、生成されるjsファイル外の別のクラスにアクセス出来ない。

サンプル

dao.coffee(dao.js)


class window.DAO
	serviceUrl : ""
	constructor : (url) ->
		@serviceUrl = url
	loadMe : (me) ->
		console.log me

生成されたクラス名のプロパティの前にwindowが付くのでファイル間を超えてアクセス出来るようになる。

(function() {

  window.DAO = (function() {

    DAO.prototype.serviceUrl = "";

init.coffee(init.js)

$ ->
	dao = new DAO("http://dao.dao/dao")
	dao.load("1234")

今回は珍しくXcodeでなくWebネタ。Webの場合はCodekit+Sass+Coffeescript+kitが楽。エディタはSublimeText2。完璧なエディタには未だ出会った事が無い…。

参考サイト

http://www.stakelon.com/2011/12/coffeescript-organizing-classes-in-separate-files/

 Posted by at 19:45

iOS CGAffineTransformまとめ

 プログラミング  Comments Off on iOS CGAffineTransformまとめ
Apr 122013
 

iOSのCGAffineTransformのCheatSheetのPDFファイル。移動、拡大、回転の図解。

CGAffineTransform cheatsheet

CGAffineTransform

iOSのCGAffineTransformの図解チートシート(cheatsheet)のPDF。今回の情報量は少ないのでお好みで。A4で印刷するとちょうどいいです。

ダウンロード(PDFファイル)は以下。

アフィン変換図解PDF

その他チートシート

iOS CGRect図解PDF

iPhoneのScreenやNavigationBarやTabbarやToolBarの高さ

いずれも無償でのPDFダウンロード及び、コピー印刷改変は自由です。

 Posted by at 15:43

bashでフォルダ内のhtmlのdoctype一括置換する

 プログラミング  Comments Off on bashでフォルダ内のhtmlのdoctype一括置換する
Mar 162013
 

Mac上のbashでhtmlタグのdoctypeを一括で置換をする時のまとめ。findとsedを組み合わせる。ネット上にあるfindとsedの組み合わせの情報はlinuxなのだと思うが、Macではエラーが出てしまうようだ。Mac上で一括置換をしたいので以下のようにする。

find -exec sed、つまりfindの-execオプションにsedを指定して該当ファイルにsedを適用してもエラーが起きる。

GnuSedをインストール

調べるとBSD系だとどうもエラーが出るようだ。GnuのSedをインストールする。brewがなければ、先に入れてみる。

http://mxcl.github.com/homebrew/


brew install gnu-sed

置換スクリプトを作成

以下指定したフォルダ内のhtmlファイル全てのdoctypeを差し替えるスクリプト。既存のdoctypeがある前提。

#!/bin/bash

echo "Input DIR : "
read dir
find $dir -type f -name "*.html" -print0 | xargs -0 gsed -i"" -e "s/<!DOCTYPE.*\">/<!DOCTYPE HTML PUBLIC \"\-\/\/W3C\/\/DTD HTML 4\.01 Transitional\/\/EN\">/"

find
-type fはファイルを対象
-nameは名前指定

sed
-i””バックアップをとる
-e 条件式を指定 条件式とはs///gのフォーマットのこと
参考URL

  • http://qiita.com/items/b775f7e082f1559707e2
  • http://technique.sonots.com/?UNIX%2Fコマンド%2Fテキスト処理%2Fsed
  • http://forums.freebsd.org/showthread.php?t=12235
  • http://tkuchiki.hatenablog.com/entry/2013/02/27/130114
  • http://www.ksknet.net/linuxai/find.html
  • http://www.nekonotechno.com/nekopress/?p=2776
 Posted by at 14:39