2013年4月13日土曜日

Node.jsのexportsとmodule.exportsについて

どうも、俺@休日中です。

最近少しだけ、プライベートでNodeをいじっています。
そういえば、初めてNodeを触ってからもう2年も経つんだなぁとシミジミ。
安定版なんかもうv0.10.3なんですね。

さて、過去のオデの日記で「node.jsで自作モジュールの作り方」というエントリーをポストしてますが、
この頃は多分あまりexportsとmodule.exportsの意味を理解していなかったようです。
※今もしていません。

今回それらを調べてみたところ、
exports
 関数をモジュール化する
module.exports
 オブジェクト(関数、配列、JSON、など)をモジュール化する
という認識で良いような気がしました。

あまり意味が分からない場合は、
Node.js Module – exports vs module.exports(※英語)にあるように、
標準は「module.exports」、補助的に「exports」という事なので、
特に深く考えずmodule.exportsを使うという認識でほぼ間違いはない気がします。

前回の僕のエントリーを元に考えます。
・exportsの場合
Person.js
exports.setName = function(name) {
  this.name = name;
};
exports.hello = function() {
  console.log("hello!");
};
exports.myName = function() {
  console.log(this.name);
};
app.js
var p = require("/path/to/Person");
p.setName("koexuka");
p.hello();  // "hello!"
p.myName();  // "koexuka"
これらはつまり、setName(name)、hello()、myName()という3つの関数を
var p = require("/path/to/person");
をp変数にオブジェクトとしてexportして使っています。
「意味的にPersonオブジェクトを生成して・・・」というより、上記3つの関数をまとめたオブジェクト、という感じでしょうか。

・module.exportsの場合]
Person.js
var Person = function(name) {
  this.name = name;
};
Person.prototype.hello = function() {
  console.log("hello");
};
Person.prototype.myName = function() {
  console.log(this.name);
};
module.exports = Person;
app.js
var Person = require("/path/to/Person");
var p = new Person("koexuka");
p.hello();  // "hello!"
p.myName();  // "koexuka"
こっちは、Personオブジェクトを取り出して使っています。

両方とも意味合いは同じですが、Person型のオブジェクトとして利用するという意味合いを持たせるには
module.exportsを利用するべきです。

ちなみにexportsとmodule.exportsが1つのファイル(例:Person.js)に混在している場合は
module.exportsが優先されてしまうので要注意。

以上でぇぇぇぇぇす。
もし間違いがあればご指摘下さいm(___)m

2013年4月8日月曜日

c++ 整数同士で割り算(除算)を行うと結果がゼロになっちゃう

どうも、俺@仕事中です。

C言語またはc++で整数同士の割り算を行った場合、
int a = 3;
int b = 5;
float z = a/b;
変数zの結果が0(ゼロ)になっちゃう!

こういう場合は

float z = (float)a/b;

のように、変数a(または変数b どちらでも)をfloat型またはdouble型でキャストしてやればOKです。
なぜなら、a/bはこの場合3/5 = 0...3 という結果になり、それがint同士で除算しているため
コンパイラに答えが0(ゼロ)と判断されてしまうからです。

以上でぇぇえぇっぇす。

2013年3月29日金曜日

CentOSにapache2.4.3をインストール

どうも、俺@寝る前です。

最近アプリ開発してばっかの俺が久しぶりにLinuxネタです。

2012/2月にapache2.4.1がリリースされて1年ちょっと経過し、
じわじわと情報が増えてきたところでようやく僕もapache2.4.3をインストールしてみました。
※2013/03/28時点での最新はv2.4.4

まずソースをDLして展開。
# wget 'http://ftp.meisei-u.ac.jp/mirror/apache/dist//httpd/httpd-2.4.3.tar.gz'
# tar zxvf httpd-2.4.3.tar.gz
# cd httpd-2.4.3
これまでだと、このまま./configureしてたのですが、2.4からはそれはNGです。
INSTALLファイルにこう書いています。
Consider if you want to use a previously installed APR and 
APR-Util (such as those provided with many OSes) or if you 
need to use the APR and APR-Util from the apr.apache.org
project. If the latter, download the latest versions and 
unpack them to ./srclib/apr and ./srclib/apr-util (no 
version numbers in the directory names) and use 
./configure's --with-included-apr option.
つまり--with-included-aprオプションを使うならaprとapr-utilをDL&展開して
./srclib以下にapr と apr-utilという名前で置きなさい。
ということらしい。
# cd ./srclib
# wget wget http://ftp.tsukuba.wide.ad.jp/software/apache//apr/apr-1.4.6.tar.gz
# wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-util-1.5.1.tar.gz
# tar zxvf apr-1.4.6.tar.gz
# tar zxvf apr-util-1.5.1.tar.gz
# mv apr-1.4.6 apr
# mv apr-util-1.5.1 apr-util
あと途中でPCREも必要だと怒られたので入れておきます。
# wget 'ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.32.tar.gz'
# tar zxvf pcre-8.32
# ./configure --prefix=/usr/local/pcre/v8.32
# make
# make install
ではapacheのインストールを行います。
※オプションは適宜ご自由に。
# ./configure --prefix=/usr/local/apache2/v2.4.3 --with-included-apr --enable-module=so --enable-mods-shared=most --enable-ssl --enable-rewrite --with-mpm=prefork --with-pcre=/usr/local/pcre/v8.32
--with-mpm=preforkオプションを付けておかないと、デフォルトでevent-mpmでインストールされてしまいます。

非同期で多アクセスには強いですが、僕のようなPHPerな開発者にはprefork-mpmがオススメです。
# make
# make install
これで上手くインストールされるはずです。

後は基本的にこれまでのバージョンのものと同じですが、apacheの設定ファイルなんかは
order allow,deny
allow from all
だったものが、v2.4からは
Require all granted
# 禁止の場合は
# Require all denied
になります。
さらには、192.168.0.10のみ許可する場合は

  Require ip 192.168.0.10

となり、逆に192.168.0.10のみ拒否する場合は

  Require all granted
  Require not ip 192.168.0.10


# または

  Require all granted
  
    Require ip 192.168.0.10
  

のようになります。
うーん、なぜ今さら変えてくるかapache.org。
これまでの書き方は非推奨となるそうで、一応まだ使えるみたいです。

あと、MaxClientsはMaxRequestWorkersに書き変わりました。


以上でぇぇぇぇす。

2013年2月26日火曜日

UITableViewで「次を表示..」ページングを実装

どうも、俺@家です。

 今日はUITableView(UITableViewControllerでも同じだけど)を使ってデータを一覧表示させたときに、 「次を表示...」というセルを用意してページングを行う方法をφ(..)メモメモ

 UITableViewに表示させるデータ(dataSource)は、
NSMutableArray *datas
に保持しているものとします。
 まずページング用のセルを表示するための準備。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section                                 
{
  // データ件数
  int count = [datas count];

  // 初期
  if (count==0) {
    return 0;

  // _offsetCountは現在の画面に表示中のデータ件数
  // 「次を表示」を出すためにcount+1件だけセル数を返すようにする
  } else if (count==_offsetCount) {
    return count+1;
  }

  // 通常はデータ件数を返す
  return count;
}
これで、保持しているデータ+1件目に「次を表示」のセルを出す事ができます。
 次に実際にセルを作ります。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  // まずデータを持った通常のセル
  if (indexPath.row!=[datas count]) {
    // Cell再利用のためのIdentifier
    static NSString *CellIdentifier = @"NormalCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell==nil) {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseidentifier:CellIdentifier] autorelease];
    }
    // 処理の必要があれば処理を書く
    return cell;

  // ページング用「次を表示」のセル(index.row==[datas count])
  } else {
    static NSString *CellIdentifier = @"NextCell";
    UITableViewCell *nextcell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (nextcell==nil) {
      nextcell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    nextcell.textLabel.text = @"次を表示";
    return nextcell;
  }
}
最後にタップされたときに次のデータを読み込ませます。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  // 選択状態解除
  [tableView deselectRowAtIndexPath:indexPath animated:YES];

  // 通常のセルが押された
  if (indexPath.row!=_offsetCount) {
    // ページ遷移などの処理
    XXViewController *viewController = [[XXViewController alloc] initWithNibName:nil bundle:nil];
    [self.navigationController pushViewController:viewController animated:YES];
    [viewController release];

  // 「次を表示」が押された
  } else {
    // 次を読み込ませるメソッド(サーバと通信するなど)
    [self loadNextData];

    // UITableViewを更新させる
    [tableView reloadData];
  }
}
これでざっとページングの完成です!
 よくある実装として、通常のセルと「次を表示」のセルとでサイズが異なる場合などは少しコツが必要なので、
 それはまた今度書きます。

 以上でぇぇえぇぇす。

2013年2月16日土曜日

UINavigationBarのナビゲーションバーに背景画像を設定する

どうも、俺@休み中です。
最近はずっとiOSアプリ開発に勤しんでいます。 

UINavigationBarを使って、ヘッダー部分(ナビゲーションバー)に画像を設定したい場合。 QiitaのUINavigationBarの背景画像を設定する方法を参考にさせてもらいました。
#import <QuartzCore/QuartzCore.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];

    // OSのバージョン取得
    float osVersion = [[[UIDevice currentDevice] systemVersion] floatValue];

    // iOS5未満
    if (osVersion < 5.0f) {
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"background.png"] stretchableImageWithLeftCapWidth:0 topCapHeight:1]];
        navBg.layer.zPosition = -FLT_MAX;
        [navigationController.navigationBar insertSubView:imageView atIndex:0];

    // iOS5以上
    } else if (osVersion >= 5.0f) {
        navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"background.png"] forBarMetrics:UIBarMetricsDefault];
    }
}
です。
 iOS5以上から
- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics

というメソッドが加わったため、iOS5未満の方法で同じように実装しても思ったように表示されません。

以上でぇぇぇえぇぇぇす。