Cocoa練習帳 -10ページ目

[OSX][iOS]はじめましてSwift

SwiftはCocoaフレームワークの為に設計されたプログラミング言語だ。

簡単なクラスの定義と実装は以下のとおり。 


import Cocoa                // 1
 
class Song: NSObject {      // 2
    var title: String       // 3
 
    init(title: String) {   // 4
        self.title = title
    }
 
    func play() {           // 5
        // ... 再生処理
    }
}

1) Cocoaフレームワークを利用する。
2) NSObjectクラスのサブクラスSongの宣言。
3) String型のtitleプロパティの宣言。
4) イニシャライザ
5) メソッドの定義

上記で定義したクラスをインスタンス変数の生成とメソッド呼び出し、プロパティの参照は以下のとおり。


let song = Song(title: "Maybellene")    // 1
song.play()                             // 2
println("\(song.title)")                // 3

1) Songクラスのインスタンス変数を生成。
2) playメソッドを呼び出す。
3) titleプロパティの値を印字。

Swiftではカテゴリを拡張(Extensions)と呼んでいる。

extension String {
    func reverse() -> String {
        var charadterArray: Charater[] = Character[]()
        for haracter in self {
            charadterArray.append(character)
        }
        var reverseString: String = ""
        for var i = characterArray.count - 1; 0 <= i; i-- {
            reverseString += characterArray[i]
        }
        return reverseString
    }
}

Stringクラスにreverseメソッドが追加された事を確認する。

let hello = ""
let reverseString = hello.reverse()
println("\(reverseString)")

プロトコルはプロトコル(Protocols)だ。先ほどのSongクラスのメソッドをプロトコルで宣言するように変更してみよう。

protocol Playable {
    func play()
    func stop()
}
 
class Song: NSObject, Playable {
    var title: String
 
    init(title: String) {
        self.title = title
    }
 
    func play() {
        println("... 再生処理")
    }
 
    func stop() {
        println("... 停止処理")
    }
}
関連情報
Cocoa in a Nutshell
Objective‐C
The Swift Programming Language
Using Swift with Cocoa and Objective-C
Swift離陸ガイド

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[OSX][iOS]関東第66回Cocoa勉強会

6月14日(土)に開催されたCocoa勉強会(関東)の報告だ。


LightBlue Bean

Arduinoが組み込まれたBluetooth周辺機器として興味を持った。デザインもいい。
ちょうど、この日、SDKが公開されたようだ。


iOSアプリの署名

署名のプロセスを解析した情報。役立つ。助かる。


OS Xの画面開発

nib/Storybord。ViewControllerについて。


irMagician

早速、Androidの参考実装のコードをクローン。ガジェット関連は楽しい!


Swift

K&R CやObjective-C 1.0は簡素だなと改めて感じた。
C言語的な部分を削った、すっきりしたパワフルな言語という事は理解できた。
他環境からの新規参入者向けという話を聞いた事があったが、そうでもないように感じた。


次回は7月末、8月頭に松戸で開催だ。


Cocoa勉強会


関連情報

【Cocoa練習帳】
http://ameblo.jp/bitz/(ミラー・サイト)

[OSX][iOS]読み仮名を得る

漢字混じりの日本文の読み仮名を得るサンプルコードを作ってみた。


- (IBAction)doRuby:(id)sender
{
	
    NSString *inputText = self.inputTextField.stringValue;
    
    NSMutableString *outputText = [[NSMutableString alloc] init];
    
    CFRange range = CFRangeMake(0, [inputText length]);
    CFLocaleRef locale = CFLocaleCopyCurrent();
    
    /* トークナイザーを作成 */
    CFStringTokenizerRef    tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault,
                                                                (CFStringRef)inputText,
                                                                range,
                                                                kCFStringTokenizerUnitWordBoundary,
                                                                locale);
    
    /* 最初の位置に */
    CFStringTokenizerTokenType  tokenType = CFStringTokenizerGoToTokenAtIndex(tokenizer, 0);
    
    /* 形態素解析 */
    while (tokenType != kCFStringTokenizerTokenNone) {
        range = CFStringTokenizerGetCurrentTokenRange(tokenizer);
        
        /* ローマ字を得る */
        CFTypeRef   latin = CFStringTokenizerCopyCurrentTokenAttribute(tokenizer,
                                                                       kCFStringTokenizerAttributeLatinTranscription);
        NSString    *romaji = (__bridge NSString *)latin;
        
        NSString    *token = [inputText substringWithRange:NSMakeRange(range.location, range.length)];
        
        /* 平仮名に変換 */
        NSMutableString *furigana = [romaji mutableCopy];
        CFStringTransform((CFMutableStringRef)furigana, NULL, kCFStringTransformLatinHiragana, false);
        
        [outputText appendString:furigana];
        DBGMSG(@"%s token(%@) latin(%@) furigana(%@)" ,__func__, token, latin, furigana);
        
        CFRelease(latin);
        tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer);
    }
    CFRelease(tokenizer);
    
    CFRelease(locale);
    
	
    [self.outputLabel setStringValue:outputText];
}
ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/mac/Ruby - GitHub
関連情報 iOSでの形態素解析
CFStringTokenizer
iOS SDK プログラミング・リファレンス【Foundation/UIKit編】
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
iOS SDK プログラミング・リファレンス【Foundation/UIKit編】/マイナビ
¥価格不明
Amazon.co.jp
iOS SDK プログラミング・リファレンス【Foundation/UIKit編】/マイナビ
¥4,298
Amazon.co.jp

[iOS]LINEで送る

iOSからLINEでメッセージを送るのは簡単だ。アプリケーションで以下のURLを呼べばいい。

line://msg/text/メッセージ

ただし、メッセージはUTF-8でURLエンコードされている事。

もし、端末にLINEがインストールされていない場合は、以下のURLで呼ぶと、iTunes StoreのLINEのページを開いてくれる。

http://line.me/R/msg/text/?メッセージ

サンプルコードでは、端末にLINEがインストールされているかどうかでURLを切り替えるようにしている。

- (IBAction)sendLINE:(id)sender
{
    NSString *text = [self.textView.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSString *urlFormat = nil;
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"line://"]]) {
        urlFormat = @"line://msg/text/%@";
    }
    else {
        urlFormat = @"http://line.me/R/msg/text/?%@";
    }
    NSString *urlString = [NSString stringWithFormat:urlFormat, text];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/SendLINE - GitHub
関連情報 設置方法 | LINEで送るボタン
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[OSX][iOS]命名規則

未だに需要があるという事で、現在では元の文書を入手する事が難しいということで、MacAppやTCLの命名規則をまとめる。

CName/TName  クラスの名前
aName  形式パラメータ
cName  静的データメンバ
fName  フラグ。通常はBoolean型データメンバ。
gName  グローバル変数
kName  定数。#define, enum, または、constで定義。
itsName  データメンバ
thename  変数。通常はローカル変数またはデータメンバ。形式パラメータに使用される事もある。
macName  Macintoshデータ構造体。データメンバまたはローカル変数として使用。
IName  CNameクラスの初期化関数。
Dispose  CNameクラスの終了関数。

少し、用語がおかしい部分があるが、当時のメモのそのまま掲載している。

【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[OSX]プロセス間通信(Distributed Objects)

今度は、Distributed Objects。まずは、プロトコルを定義。


@protocol RemoteObjectProtocol
- (oneway void)receiveString:(NSString *)string;
@end

サーバ側を実装。クライアント側からのメソッド呼び出しに対応。


@interface AppDelegate () <RemoteObjectProtocol>
- (void)_registerForDistributedObjects;
@end
 
@implementation AppDelegate
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [self _registerForDistributedObjects];
}
 
- (void)_registerForDistributedObjects
{
    NSConnection    *conn = [NSConnection defaultConnection];
    [conn setRootObject:self];
    if ([conn registerName:@"DistributedServer"] == NO) {
        NSLog(@"%s error", __func__);
    }
}
 
- (oneway void)receiveString:(NSString *)string
{
    [self.label setStringValue:string];
}
 
@end

次は、クライアント側。


@interface AppDelegate ()
- (void)_postForDistributedObjects;
@end
 
@implementation AppDelegate
 
- (IBAction)postForDistributedObjects:(id)sender
{
    [self _postForDistributedObjects];
}
 
- (void)_postForDistributedObjects
{
    id  remoteObject;
    remoteObject = [NSConnection rootProxyForConnectionWithRegisteredName:@"DistributedServer"
                                                                     host:@""];
    [remoteObject setProtocolForProxy:@protocol(RemoteObjectProtocol)];
    [remoteObject receiveString:[NSString stringWithFormat:@"%@", [[NSDate date] description]]];
}
 
@end

名前DistributedServerでサーバを探して、プロトコルRemoteObjectProtocolのメソッドを呼ぶと、サーバ側のメソッドが実行される。


ソースコード
GitHubからどうぞ。

関連情報

【Cocoa練習帳】
Cocoa in a Nutshell: A Desktop Quick Reference/Oreilly & Associates Inc
¥5,008
Amazon.co.jp

[OSX]プロセス間通信(Distributed Notifications)

最近はiOSのアプリケーション開発の比率が高くなっているので利用する機会が減ってきているが、OSXでは異なるアプリケーションに対して通知を送る事ができる。


通知を受け取る側(DistributedServer)のコードは以下のとおり。


@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSLog(@"%s", __func__);
    [self _registerForNotes];
}
 
- (void)_registerForNotes
{
    NSLog(@"%s", __func__);
    NSDistributedNotificationCenter *dnc = [NSDistributedNotificationCenter defaultCenter];
    [dnc addObserver:self
            selector:@selector(_handleDistributedNote:)
                name:@"DemoDistributedNote"
              object:nil];
}
 
- (void)_handleDistributedNote:(NSNotification *)note
{
    NSLog(@"%s Recieived Distributed Notification!:%@", __func__, note);
}
@end

通知を送る側(DistributedClient)のコードは以下のとおり。


@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSLog(@"%s", __func__);
    [self _postNotes];
}
 
- (void)_postNotes
{
    NSLog(@"%s", __func__);
    NSDistributedNotificationCenter *dnc = [NSDistributedNotificationCenter defaultCenter];
    [dnc postNotificationName:@"DemoDistributedNote"
                       object:nil];
}
@end

DistributedServerを起動した後に、DistributedClientを起動すると、アプリケーション間で通知が送られることが確認できる。


ソースコード
GitHubからどうぞ。

関連情報

【Cocoa練習帳】
Cocoa in a Nutshell: A Desktop Quick Reference/Oreilly & Associates Inc
¥5,008
Amazon.co.jp

[OSX]プロセス間通信(NSPipe)

Cocoaのプロセス間通信について調べてみた。今回はパイプだ。


/* ディレクトリ/配下の一覧を取得するプロセスを用意 */
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/ls"];
[task setArguments:[NSArray arrayWithObject:@"/"]];
 
/* 渡されたデータを読み取るパイプを用意 */
NSPipe *pipe = [[NSPipe alloc] init];
NSFileHandle *readEnd = [pipe fileHandleForReading];
 
/* 先ほどのプロセスの標準出力にパイプを繋げる */
[task setStandardOutput:pipe];
 
/* 実行 */
[task launch];
 
/* パイプに渡されたデータを印字 */
NSData *stdOutData = [readEnd availableData];
NSLog(@"%@", [[NSString alloc] initWithData:stdOutData encoding:NSUTF8StringEncoding]);

これに似たコマンドは、ちょっと違うが以下かな?


$ /bin/ls / | tee

ソースコード
GitHubからどうぞ。

関連情報

【Cocoa練習帳】
Cocoa in a Nutshell: A Desktop Quick Reference .../O’Reilly Media
¥価格不明
Amazon.co.jp

[iOS][Android]すれちがい通信(その8)

Android 4.3からBluetooth LEに対応したということで、Nexus 7 (2012)を使って、iBeaconの検出に挑戦してみた。

今回の記事は、各種ブログから得られた情報を参考にしているのだが、その大半は内容が似ている。つまり、元となる情報があるようだ。しかし、どれが元の情報なのか分からず、関連情報としてあげてみたが、それに元の情報が含まれているのか自身がない。含まれていない場合は、申し訳ない。

AndroidManifest.xmlファイルに特権を追加する。

<manifest ...>
    ...
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    ...
</manifest>

BLUETOOTHでBLE機器との通信を。BLUETOOTH_ADMINでBLE機器の検出を。最後のは、BLE対応端末でのみ動作という意味だ。

MainActivity.javaに必要なクラスをインポートする。

import android.content.Context;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattService;
import android.content.pm.PackageManager;
import android.widget.Toast;
import android.util.Log;

インスタンス変数を宣言しておく。

    private final String TAG = "Wibree-Main";
    private BluetoothAdapter mBluetoothAdapter;

今回は、簡単なお試しなので、onCreate()メソッドに必要なコードを記述。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		
        /* BLE対応の確認 */
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "not support", Toast.LENGTH_SHORT).show();
            finish();
        }
		
        /* Bluetooth Adapter */
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
		
        /* Bluetooth LEデバイスの検索 */
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    }

コールバックの実装。この部分は、参考にしたサイトのコードを丸写し。

private BluetoothAdapter.LeScanCallback mLeScanCallback =

new BluetoothAdapter.LeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device,

int rssi,

byte[] scanRecord) {

if (scanRecord.length > 30) {

   if ((scanRecord[5] == (byte)0x4c)

    && (scanRecord[6] == (byte)0x00)

    && (scanRecord[7] == (byte)0x02)

    && (scanRecord[8] == (byte)0x15)) {

           String uuid = IntToHex2(scanRecord[9] & 0xff) 

           + IntToHex2(scanRecord[10] & 0xff)

           + IntToHex2(scanRecord[11] & 0xff)

           + IntToHex2(scanRecord[12] & 0xff)

           + "-"

           + IntToHex2(scanRecord[13] & 0xff)

           + IntToHex2(scanRecord[14] & 0xff)

           + "-"

           + IntToHex2(scanRecord[15] & 0xff)

           + IntToHex2(scanRecord[16] & 0xff)

           + "-"

           + IntToHex2(scanRecord[17] & 0xff)

           + IntToHex2(scanRecord[18] & 0xff)

           + "-"

           + IntToHex2(scanRecord[19] & 0xff)

           + IntToHex2(scanRecord[20] & 0xff)

           + IntToHex2(scanRecord[21] & 0xff)

           + IntToHex2(scanRecord[22] & 0xff)

           + IntToHex2(scanRecord[23] & 0xff)

           + IntToHex2(scanRecord[24] & 0xff);

           String major = IntToHex2(scanRecord[25] & 0xff) + IntToHex2(scanRecord[26] & 0xff);

           String minor = IntToHex2(scanRecord[27] & 0xff) + IntToHex2(scanRecord[28] & 0xff);

           

           Log.d(TAG, "uuid:" + uuid);

           Log.d(TAG, "major:" + major);

           Log.d(TAG, "minor:" + minor);

       }

}

}

};

private String IntToHex2(int i) {

   char hex_2[] = {Character.forDigit((i>>4) & 0x0f,16),Character.forDigit(i&0x0f, 16)};

   String hex_2_str = new String(hex_2);

   return hex_2_str.toUpperCase();

}

iBeaconは、BLEのアドバタイズメントに情報を埋め込んでいるので、スキャンしたデータから識別子やメジャー/マイナー番号がとれる。

さあ、これを実機で実行だ!あれ?動かない。BLE対応の確認で引っかかる!

Nexus 7 (2012)は、ハード的にはBLE対応は可能みたいだが、OSで未対応としているみたい。試せなくで残念!

ソースコード
GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/android/Wibree - GitHub
関連情報
Core Bluetooth Programming Guide
BTLE Central Peripheral Transfer
【連載】Bluetooth LE (5) Android 4.3 で Bluetooth LE 機器を使う
AndroidでiBeacon信号を受信してみよう
aBeacon ~iBeacon を Android で受信する~

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

第65回Cocoa勉強会(関東)

4月5日(土)に開催されたCocoa勉強会の報告だ。

「NSURLSessionでのバックグランドダウンロード」Mac/iOS
以前の発表のプラスαの内容で、その後の経験が盛り込まれ、とても参考になった。

「すれ違い通信[Bluetooth LEとiBeacon]」iOS
CoreBluetoothを直接呼ぶ場合と、iBeaconのAPI使った同様なすれ違い通信についての発表だ。

「ガリレオをMacで動作させるまで」OSX
GalileoとirMagicianの紹介。Macintoshでエアコンのリモコン操作等、やりたいことがどんどん出てきた。

「はじめてのスプライトキット」iOS
SpriteKitについての疑問点が解消できてよかった。サンプルが充実している。

次回は、6月14日(土)に、本日と同じ会場で開催予定だ。

関連情報
Cocoa勉強会(関東)
活動報告
connpass

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)