2012年5月11日金曜日

Objective-Cで 'Cannot find interface declaration for 'XXXXClass', superclass of 'ZZZZClass'...'が出る

どうも、俺@昼休みです。
タイトルの通り、Xcodeでコンパイルすると
「Cannot find interface declaration for 'XXXXClass', superclass of 'ZZZZClass'...」のエラーが出て困っていた俺へのめも。
何が起こってるかというと、簡単に言うと循環参照。

Objective-Cのクラスの前方宣言がないと困ること - アールケー開発に同じような内容の詳しい解説があります。

ClassA
#import "ClassB.h"
@interface ClassA: NSObject
{
  ClassB *b;
}
@end

ClassB
#import "ClassA.h"
@interface ClassB: NSObject
{
  ClassA *a;
}
@end
ClassAとClassBがそれぞれのヘッダファイルでお互いをimportしていて、
かつどちらかでどちらかのインスタンス変数を持っている、
またはどちらかのクラスを継承している、
ような場合にタイトルのような問題が発生します。
※コンソールからgccとかで直接コンパイルした場合は、

In file included from ClassA.h:2,
                 from ClassA.m:1:
ClassB.h:6: error: expected specifier-qualifier-list before ‘ClassA'
のようなエラーが出ます。困ったもんだ。

問題の詳細はコンパイルの処理にあり、
■ClassA.hのコンパイル
ClassA.h内で#import "ClassB.h"が見つかった時点でClassB.hをインポート(解析)する。
ClassB.h内にある#import "ClassA.h"が見つかりClassA.hをインポート(解析)するはずだが、#import宣言はネストしながらインポートしないため、実際はClassA.hのインポートは行われない。
ClassB.h内のClassAインスタンス変数の定義(ClassA *a;)で、ClassAの宣言が見つからないのでエラーとなる。
、、、そうです。

こういうような場合、#import宣言をやめて@classを使い前方宣言で対処できるのであればそれで解決できます。

ClassA
@class ClassB;
@interface ClassA: NSObject
{
  ClassB *b;
}
@end

ClassB
@class ClassA;
@interface ClassB: NSObject
{
  ClassA *a;
}
@end


ただし、対象のクラスを継承していたり、処理内で対象のクラスをallocしたりしてる場合は#importを使わなければいけません。


以上でェェエェす。


macでlsしたときの@(アットマーク)

どうも、俺@今から仕事です。
Mac(Tiger以上)のターミナル上で

$ ls -l
したときにファイルやディレクトリの属性に@(アットマーク)が付いている場合があります。

$ ls -l
-rw-r--r--   1 username  staff    411 12 12 17:44 hoge.txt
-rw-r--r--   1 username  staff  26945  5 11 09:39 foo.txt
-rw-r--r--@  1 username  staff   1766  5 11 09:37 fuga.txt #←こいつ!

なんだこれは?ということで調べてみると、Mac Tigerで導入されたファイルリソース(Extended Attributes)というものらしいです。
※Tigerではデフォルトで無効化されており、実質Leopardから見られる。

拡張属性というもので、Spotlightなどの検索で利用されるらしい。
特にその存在が邪魔するというともないとは思いますが、「きもい!消したい!」という人(俺)は、
1)まず確認
$ ls -l@
-rw-r--r--   1 username  staff    411 12 12 17:44 hoge.txt
-rw-r--r--   1 username  staff  26945  5 11 09:39 foo.txt
-rw-r--r--@  1 username  staff   1766  5 11 09:37 fuga.txt
        com.apple.metadata:kMDItemWhereFroms      174
        com.apple.quarantine       70
lsに-@を付けることでその詳細が確認できます。
ここにある、com.apple.metadata:kMDItemWhereFromsとcom.apple.quarantineはダウンロードしたファイルにつく属性みたい。
$ xattr -d com.apple.metadata:kMKItemWhereFroms fuga.txt
$ xattr -d com.apple.quarantine fuga.txt
これで削除できます。

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

2012年5月10日木曜日

objective-cのクラスでプロパティをprivateに

どうも、俺@残業中です。
今日はObjective-Cのクラスで、プロパティ(@property)宣言した値をprivateのように扱う方法めもです。

MyClass.h
@interface MyClass {

  // インスタンス変数
  NSString *string;
}
@end

MyClass.m
#import "MyClass.h"
// 無名カテゴリ宣言
@interface MyClass()
@property (nonatomic, retain) NSString *string;
@end

@implementation MyClass
@synthesize string;
@end
これでオッケー。

ヘッダファイルにプロパティを書いてしまうと、外部からそのプロパティにアクセス出来てしまうことが用意に想像できてしまい、意識せずに外部からそのプロパティへアクセスしてしまいがちです。
プログラマが一人であったり、小規模なプロジェクトであれば問題ありませんが、「このインスタンス変数は外部からアクセスしちゃあかんでぇ」と意識させたい場合などにはこの方法が便利です。

ただし、Objective-Cの特性で外部からのアクセスを完全に遮断することは出来ず、やろうと思えばアクセス出来ちゃいますが、こればかりはどうしようもありません。あしからず。


以上でぇぇぇぇえぇす。

2012年4月30日月曜日

php-fpmで”Starting php-fpm .... failed"になる

どうも、俺@連休満喫中です。
今日はphp-fpmを起動させたときに起こったトラブルシューティングです。

phpv5.4.1をソースからインストールし、php-fpmの起動スクリプトを/etc/init.d以下へ設置します。

# cp php-5.4.1/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
# chmod +x /etc/init.d/php-fpm

これで起動させます。

# service php-fpm start
Starting php-fpm .................................... failed
Oh!No! 起動失敗かよ!
と思いきや、psコマンドで見るとphp-fpm動いてる。

# ps axuw -H

root     26983  0.0  0.3  98380  4056 ?        Ss   00:53   0:00   php-fpm: master process (/usr/local/php-5.4.1/etc/php-fpm.conf)                    
nginx    26984  0.0  0.4  98380  4412 ?        S    00:53   0:00     php-fpm: pool www                                                                  
nginx    26985  0.0  0.4  98380  4420 ?        S    00:53   0:00     php-fpm: pool www   

コンソール上では起動失敗しているように見えますが、php-fpmプロセスは起動しています。なのでこのままでも動作はしますが毎回起動する度にエラーが出るので気持ち悪いです。
多分ですが、起動後にpidファイルの生成がうまくいかずエラー表記になってるみたいです。今度調べとかないと。。

なんて状況で困っているあなた。

調べてると、
http://serverfault.com/questions/195966/php-fpm-getting-a-failed-message-but-the-processes-start-ok
に答えがありました。
php-fpm.confファイルにあるpid fileに関するディレクトリがコメントアウトされているので「;(セミコロン)」を外せば良いようです。


# vim /path/to/php-fpm.comf
-----------------------------------------

 25 ;pid = run/php-fpm.pid
 26 pid = run/php-fpm.pid
これでよし。

これで起動させれば、問題なく起動できます。


以上でぇぇぇえす。



2012年4月6日金曜日

[Node]expressで”Cannot find module ‘express’が出る

どうも、俺@寝る前です。
前回の内容とかぶるのですが。


開発スピードの超早いNodeですが、あまりにも早過ぎるため開発中にどんどん新しいバージョンがリリースされてしまいます。
流行りもの好きな人にとっては居ても立ってもいられない状況であり、それを解決するためのツールの一つにnaveがあります。
もはや説明するまでもなく、Nodeのバージョン管理ツールです。

今日はnaveを使ってタイトルのようなエラー、または他にもNodeで使うはずのモジュールが「Cannot findだぜ!」となる人へ。

$ node app.jp
node.js:12
throw e; / process.nextTick error, or ‘error’ event on first tick
^
Error: Cannot find module ‘express'

要は環境変数NODE_PATHに対し、正しくNodeモジュール群のパスを示せれば良いので、

export NODE_PATH=/path/to/node_modules
とすれば良いのですが、
「/path/to/node_modulesってどこだよっ!?」って人は、
naveをインストールしたディレクトリを起点に

[naveインストールディレクトリ]/installed/[バージョン番号]/lib/node_modules
にあります。

これで解決なのですが、毎回 export 打つのは面倒です。なので、

$ vim ~/.zshrc
---------------------------------
export NODE_PATH=/path/to/node_modules
としても良いのですが、.zshrcにハードコーディングするとバージョンが変わるたびに.zshrcを書き換えなければいけません。
そこで、もう一つの代案として、

$ vim /path/to/nave.sh
-----------------------------------
# nave_use()を探して、その関数内にある
local lib=“$prefix/lib/node:$prefix/lib/node_modules
と変更する方法でも良いです。
ちなみにnave.shは僕の環境だと

$ ls -la ~/.nave

合計 116
drwxr-xr-x 5  koexuka groupname  4096  3月  6 00:21 .
drwxr-xr-x 6 koexuka groupname  4096  3月  6 00:16 ..
drwxr-xr-x 8 koexuka groupname  4096  3月  3 14:33 .git
-rw-r--r-- 1 koexuka groupname    14  3月  3 14:33 .gitignore
-rw-r--r-- 1 koexuka groupname    14  3月  3 14:33 .npmignore
-rw-r--r-- 1 koexuka groupname     9  3月  3 17:24 .zshenv
-rw-r--r-- 1 koexuka groupname   248  3月  3 14:33 AUTHORS
-rw-r--r-- 1 koexuka groupname  4002  3月  3 14:33 README.md
drwxr-xr-x 4 koexuka groupname  4096  3月  4 15:04 installed
-rwxr-xr-x 1 koexuka groupname 12918  3月  4 15:06 nave.sh
-rw-r--r-- 1 koexuka groupname   345  3月  4 15:02 naverc
-rw-r--r-- 1 koexuka groupname   197  3月  3 14:33 package.json
drwxr-xr-x 3 koexuka groupname  4096  3月  4 15:04 src
にあります。

以上でぇぇぇぇぇぇす。