Interface Builderを使わない作り方(View-based編)

1.Xcodeを立ち上げ、「Create a new Xcode project」を選択。
20120217_210329

2.プロジェクトテンプレートから「View-based Application」を選択する。
20120217_210348

プロジェクト名の欄に"viewbase"と入力し、Nextボタンを押す。
20120217_210400

保存先を決定するダイアログが出るので、好きな場所を選んでCreateボタンを押す。
20120217_210414

3.xibファイルを削除する。
MainWindow.xibとviewbaseViewController.xibの2つを削除。
20120217_210857

ポップアップメニューからDeleteを選択すると確認ダイアログが出るので、Deleteボタンを押す。
20120217_211017

4.plistファイルの「Main nib file base name」キーを削除。
20120217_211216

5.main.mの内容を修正。
UIApplicationMain関数の第4引数を、UIApplicationのデリゲートクラス名(ここでは、"viewbaseAppDelegate")に修正。

int main(int argc, char *argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  int retVal = UIApplicationMain(argc, argv, nil, @"viewbaseAppDelegate");
  [pool release];
  return retVal;
}

6.viewbaseAppDelegate.mに、不足分のコードを追加する。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // ウィンドウの作成
  CGRect frame = [[UIScreen mainScreen] bounds];
  self.window = [[UIWindow alloc] initWithFrame:frame];
  // ビューコントローラの作成
  self.viewController = [[viewbaseViewController alloc] init];

  self.window.rootViewController = self.viewController;
  [self.window makeKeyAndVisible];
  return YES;
}

| | コメント (1) | トラックバック (0)

Interface Builderを使わない作り方(Window-based編)

Xcodeでプロジェクトを作成すると、Interface Builder用のファイルも一緒に作られてしまいます。
そこで、Interface Builderに頼らずウィンドウベースなアプリを作る手順を紹介します。

1.Xcodeを立ち上げ、「Create a new Xcode project」を選択。
20120217_203835

2.プロジェクトテンプレートから「Window-based Application」を選択する。
20120217_203845

プロジェクト名の欄に"winbase"と入力し、Nextボタンを押す。
20120217_203858

保存先を決定するダイアログが出るので、好きな場所を選んでCreateボタンを押す。
20120217_203902

3.MainWindow.xibを削除する。
ポップアップメニューからDeleteを選択すると確認ダイアログが出るので、Deleteボタンを押す。
20120217_204006

20120217_204043

4.plistファイルの「Main nib file base name」キーを削除。
20120217_204124

5.main.mの内容を修正。
UIApplicationMain関数の第4引数を、UIApplicationのデリゲートクラス名(ここでは、"winbaseAppDelegate")に修正。

int main(int argc, char *argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  int retVal = UIApplicationMain(argc, argv, nil, @"winbaseAppDelegate");
  [pool release];
  return retVal;
}

6.winbaseAppDelegate.mに、不足分のコードを追加する。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // ウィンドウを作成
  CGRect frame = [[UIScreen mainScreen] bounds];
  self.window = [[UIWindow alloc] initWithFrame:frame];
  // このままだと真っ暗なので確認用のコードを追加
  self.window.backgroundColor = [UIColor blueColor];

  [self.window makeKeyAndVisible];
  return YES;
}

以上で終わり。
あとは、プロジェクトを実行してエラーが出なければ成功!

| | コメント (0) | トラックバック (0)

Objective-Cによる文字列の扱い

Objective-Cでは、文字列リテラルの書き方が他の言語と違うので、うっかりC言語用の方で記述してしまいます…。

■文字列リテラル
"" --- C言語用
@"" --- NSString用

■よく使う文字列系のクラス
NSString --- 文字列を扱うクラス。
NSLog --- デバッガコンソールへ文字列を出力するクラス。

■置換子について(代表的なもの)
%@ --- NSString用(%sとは違うので注意)
%% --- "%"文字表示
%d --- int符号付き10進表示
%u --- int符号なし10進表示
%f --- 浮動小数点数表示

■文字列クラスの生成例

// 文字列の生成
NSString *str = @"nekozita";
// 文字列配列の生成
NSString *ary[] = {@"a", @"b", @"c"};

| | コメント (0) | トラックバック (0)

iPhoneの入力処理(タッチイベント処理)

お絵かきソフトやゲームの入力処理では、タッチした座標を取得したいことがあります。
そんな時はUIResponder継承クラスから、タッチ情報を取得します。

>作成手順
1.「View-based Application」プロジェクトを作成

2.UIResponder継承クラスに、タッチ系のメソッドを上書き

タッチ操作系のメソッド
touchesBegan --- 画面をタッチすると呼び出される
touchesCancelled --- タッチイベントが取り消されたら呼び出される
touchesEnded --- 指を離すと呼び出される
touchesMoved --- 指を動かすと呼び出される

3.touches引数から、指の数、タップ回数、タッチ座標などを取得
touchesを一度UITouchで受け取り、そこから詳細なタッチ情報を取り出します。

// タッチ座標を取得
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint pos = [touch locationInView:self.view];
}
// 指の数、タップ回数、タッチ座標を取得
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSUInteger count = [touches count]; // 指の数
    UITouch *touch = [touches anyObject];
    NSUInteger tapCount = [touch tapCount]; // タップ回数
    CGPoint pos = [touch locationInView:self.view]; // タッチ座標
}

| | コメント (0) | トラックバック (0)

iPhoneを傾けると、ビューが自動回転するアプリを作る

Xcodeでプロジェクトを作成しただけでは
iPhoneを傾けてもビューが回転してくれません。

なんだか、めんどくさそうですが
shouldAutorotateToInterfaceOrientationメソッド内を少し修正するだけで対応できます。

>作り方の手順
1.プロジェクトをView-based Applicationで作成
2.shouldAutorotateToInterfaceOrientationメソッドの戻り値を修正する
UIViewControllerの継承クラス)

interfaceOrientation引数に回転方向が入っているので
許可したい向きのみ、YESを返すようにします。

UIInterfaceOrientationPortrait
正常な状態

UIInterfaceOrientationLandscapeLeft
右に倒した(ホームボタンが左にある状態)

UIInterfaceOrientationLandscapeRight
左に倒した(ホームボタンが右にある状態)

UIInterfaceOrientationPortraitUpsideDown
逆さまにした状態

※動作で考えると左右の状態が混乱します。ホームボタンの位置で見ると分かりやすいです。

>コード例
全方向の回転を許可

// 全方向の回転を許可する
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

3方向の回転を許可(逆さのみ回転しない)

// 左・通常・右方向へ倒したときのみビュー回転をさせる
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    BOOL normal = (interfaceOrientation == UIInterfaceOrientationPortrait);
    BOOL turnLeft = (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    BOOL turnRight = (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
//    BOOL upsideDown = (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
    
    return normal || turnLeft || turnRight;
}

| | コメント (0) | トラックバック (0)

エクセルで乱数分析

下のグラフは、ヒストグラムによる乱数分析結果です。

■まずは、RAND関数
Rand1各乱数値が、だいたい平均に近い発生回数になるはず・・・。

■エクセルのNORMINV関数を使った正規乱数?
Rand2中央値に近くなるほど、発生回数が多くなる。

■中心極限定理を使って、正規乱数を擬似的に再現
Rand3擬似的とはいえ、いい感じで正規分布に近づいてます。
十分実用できそう。

■指数乱数
Rand4ガ◯ャポンみたいなアイテム出現管理に使えそう。
※ 0に近い値は使えなさそうだったので、0.1未満はグラフから外しました。

| | コメント (0) | トラックバック (0)

ネットワーク・プログラミングに挑戦! (3)

今回は、TCP通信のプログラムです。
前回のUDPとは異なり、通信前に接続確認の処理が必要となります。

■TCP通信のおおまかな手順
・ソケットの作成 - socket()
・接続先の設定 - sockaddr_in構造体/bind()

サーバ側
・接続の受入れ - listen()
・クライアントへ接続 - accept()
クライアント側
・サーバへ接続 - connect()

・データ通信 - send()/recv()

TCP通信では、通信前に接続確認をする必要があり
以下3つの関数を使います。

listen()
accept()
connect()

サーバとクライアントで呼び出す関数が違う点だけ
注意します。

■TCPサーバ側プログラム
ws2_32.libが必要

#include <stdio.h>
#include <WinSock2.h>

int main()
{
  WSADATA wsadata;
  WSAStartup(MAKEWORD(2, 0), &wsadata);

  // ここから TCP通信
  SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(12345);
  addr.sin_addr.S_un.S_addr = INADDR_ANY;
  // サーバー処理
  bind(s, (struct sockaddr *)&addr, sizeof(addr));
  listen(s, 5);
  struct sockaddr_in client;
  int client_size = sizeof(client);
  SOCKET s0 = accept(s, (struct sockaddr *)&client, &client_size);
  send(s0, "Hello", 5, 0);
  closesocket(s0);
  closesocket(s);

  WSACleanup();

  printf("client: Hello\n");
  getchar();
  return 0;
}

■TCPクライアント側プログラム
ws2_32.libが必要

#include <stdio.h>
#include <WinSock2.h>

int main()
{
  WSADATA wsadata;
  WSAStartup(MAKEWORD(2, 0), &wsadata);

  // ここから TCP通信
  SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(12345);
  addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
  // クライアント処理
  connect(s,(struct sockaddr *)&addr,sizeof(addr));
  char buf[32];
  memset(buf,0,sizeof(buf));
  recv(s,buf,sizeof(buf),0);
  closesocket(s);

  WSACleanup();

  printf("%s を送信しました\n", buf);
  getchar();
  return 0;
}

| | コメント (0) | トラックバック (0)

ネットワーク・プログラミングに挑戦! (2)

ソケットプログラミングに挑戦してみます。

詳細がよく理解できていないのですが
なるべくUDP通信に着目したいので
エラー処理をすべて無視します。

■UDP通信のおおまかな手順
・ソケットの作成 - socket()
・接続先の設定 - sockaddr_in構造体
・データの送受信 - sendto()/recv()
となります。

具体的にコードを引用すると

■ソケットの作成
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
UDP通信では、SOCK_DGRAMを指定するようです。

■接続先の設定
ここから、ちょっとごちゃごちゃします。

必要最低限の設定は

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(12345); // ポート番号

そして、サーバー側なら
sockaddr_in構造体にINADDR_ANYを設定

addr
  .sin_addr
  .S_un
  .S_addr = INADDR_ANY;

クライアント側ならIPアドレスを指定

addr
  .sin_addr
  .S_un
  .S_addr = 
  inet_addr("127.0.0.1"); // IPアドレス

■データの送受信

受信関数
recv(ソケット, 受信データ, 最大受信サイズ, フラグ);

送信関数
sendto(ソケット, 送信データ, 送信データサイズ, フラグ, sockaddr系構造体へのポインタ, sockaddr系構造体のサイズ);

ほかにも、送受信の関数があるようですが…
とりあえず、UDPのときは上記関数を使うものだと割り切って使いました。

以上のプログラムをまとめると…

■UDPサーバー側のプログラム
ws2_32.libライブラリが必要

#include <stdio.h>
#include <winsock2.h>

int main()
{
  WSADATA wsadata;
  WSAStartup(MAKEWORD(2, 0), &wsadata);

  // ここから UDP通信
  SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(12345);
  addr.sin_addr.S_un.S_addr = INADDR_ANY;
  // 受信処理
  bind(s, (struct sockaddr *)&addr, sizeof(addr));
  char buf[2048];
  memset(buf, 0, sizeof(buf));
  recv(s, buf, sizeof(buf), 0);
  closesocket(s);

  WSACleanup();

  printf("client: %s\n", buf);
  getchar();
  return 0;
}

■UDPクライアント側のプログラム
ws2_32.libライブラリが必要

#include <stdio.h>
#include <winsock2.h>

int main()
{
  WSADATA wsadata;
  WSAStartup(MAKEWORD(2, 0), &wsadata);

  // ここから UDP通信
  SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(12345);
  addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
  // "Hello"を送信
  sendto(s, "Hello", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
  closesocket(s);

  WSACleanup();

  printf("Hello を送信しました\n");
  getchar();
  return 0;
}

うーん、Windowsプログラミングって難しいです。

| | コメント (0) | トラックバック (0)

ネットワーク・プログラミングに挑戦! (1)

ネットワークのプログラムって、サンプルコードがいまいちよく理解できない…。
なので、一番シンプルなところから始めてみます。
Win32APIと、せっかく携帯もやっているのでiアプリでも組んでみました。

■Win32 (winsock) - winsock2.h/ws2_32.libが必要 -
※手抜きプログラムなので、エラー処理してません。

WSADATA wsadata;
WSAStartup(MAKEWORD(2, 0), &wsadata);
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
WSACleanup();

Win32APIはこれ以上進むと、ちょっと複雑…。
この後、TCP/IPかUDPを利用するかでプログラムが変わるみたい。

■Java (DoJa)
※手抜きなので、クローズのnullチェックしてません。

String url = "http://";
HttpConnection http = null;
try{
	http = (HttpConnection) Connector.open(url);
	http.setRequestMethod(HttpConnection.GET);
	http.connect();
} catch (IOException e){
} finally{
	try{ http.close(); } catch (IOException e){}
}

Javaは簡単で、connect以降はStream系のクラスを使ってデータの送受信すればいいだけです。

改めてJavaと比較すると
Windows APIは、関数名に専門用語使ってるから
処理内容が読み取りづらいです。

| | コメント (0) | トラックバック (0)

reverseの便利な使い方 [Perl]

バイナリファイルの中には
リトルエンディアン形式で記録されたものがあります。
たとえば、4バイト分を元に戻すプログラムは

my $data = "\xff\x12\x34\xaa";

# little endian (shift/bit)
$data = hex(unpack("H*", $data));
$en  = ($data       & 255) << 24;
$en |= ($data >>  8 & 255) << 16;
$en |= ($data >> 16 & 255) << 8;
$en |= ($data >> 24 & 255);

printf("%x\t%x\n", $data, $en);

このようになりますが
Perlの場合、reverse関数を使うという方法もあります。

my $data = "\xff\x12\x34\xaa";

# little endian (reverse)
$en = hex(unpack("H*", reverse $data));

print unpack("H*", $data);
printf("\t%x\n", $en);

| | コメント (0) | トラックバック (0)

«コーディングミスを検出する構文チェック機能 [Padre/Perl]