Xcode の Quick Look で艦娘をデバッグする

Xcode 5から導入された、デバッグ時の Quick Look機能、デバッグ時にオブジェクトの情報をグラフィカルに見ることができてとっても便利ですよね。 Xcode 5.1からは、システムクラスに加えて、カスタムクラスのQuick Look機能も使えるようになっているので、さっそく使ってみました。

普通の Quick Look

普通のってなんだよって感じですが、いわゆる、組み込みのシステムクラスのQuick Look。 何も特別な設定をしなくても使えるQuick Lookです。

使い方は簡単。 オブジェクトの上にマウスオーバーすると、ツールチップのような小さいダイアログが表示されます。 そのツールチップの上の、「目」のように見えるアイコンをクリックします。 すると、こんな感じでオブジェクトの中身がグラフィカルに見れるようになります。

system

なお、iOSのシステムクラスで Quick Lookに対応しているのは下記のクラスです。 (Xcode5.1 では、UIColorが対応していないのが残念。カスタムクラスのQuick Lookでは対応しているんですが。)

UIImage、UIImageView、CIImage、UIBezirePath、CLLocation、UIView、NSString、NSAttributedString、NSData、NSURL

カスタムクラスでの Quick Look

さて、自分の作ったカスタムクラスでこのQuick Look機能を使いたい場合ですが、debugQuickLookObjectというメソッドを実装します。

このメソッドを実装することで、Quick Look画面に表示したいオブジェクトを設定できるので、独自のQuick Look機能をサポートすることができます。 返すことができるのは、このクラスのオブジェクトです。 UIImage、UIImageView、CIImage、UIBezirePath、CLLocation、UIView、NSString、NSAttributedString、NSData、NSURL、UIColor

カスタムクラスでUIImageを返す

例えば、UIImageを返したいときには、こう実装します。

- (id)debugQuickLookObject
{
UIImage* image1 = [UIImage imageNamed:@"flower.jpg"];
return image1;
}

カスタムクラスでUIColorを返す

UIColorを返したいときには、こう実装します。

- (id)debugQuickLookObject
{
UIColor* color1 = [UIColor colorWithRed:0.5 green:0.4 blue:0.3 alpha:0.7];
return color1;
}

UIColor

カスタムクラスでUIBezierPathを返す

UIBezierPathを返したいときにはこちら。

- (id)debugQuickLookObject
{
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(120.0f, 100.0f, 80.0f, 150.0f)];
return circle;
}

bezier

カスタムクラスでCLLocationを返す

CLLocationを返したいときにはこちら。 Quick Lookに表示された地図で場所を見ることもできるので、結構便利です。

- (id)debugQuickLookObject
{
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:135.0 longitude:35.0];
return location1;
}

location

カスタムクラスで独自のUIViewを返す

そして、もちろんUIViewも返せるので、独自に実装したデバッグビューなどを返すこともできます。

こちらの例は、独自「艦娘」クラスのデバッグビューの例。 ベースの画像の上に、艦娘のデータなどをのせてみました。

(なお、このクラスでは、変数名に日本語を使ってみました。意外とコードが見やすくなってます。)

- (id)debugQuickLookObject
{ 
    UIImageView* baseView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 487, 374)];

<pre><code>UIImage* baseImage = [UIImage imageNamed:@"kanbase.png"];
baseView.image = baseImage;

UILabel* labelName = [[UILabel alloc] initWithFrame:CGRectMake(20, 3, 100, 50)];
labelName.text = self.船名;
labelName.font = [UIFont systemFontOfSize:20.0];
[baseView addSubview:labelName];

UIImageView* shipView = [[UIImageView alloc] initWithFrame:CGRectMake(245, 15, 218, 300)];
shipView.image = [UIImage imageNamed:self.写真];
[baseView addSubview:shipView];

UILabel* labelLevel = [[UILabel alloc] initWithFrame:CGRectMake(174, 2, 50, 50)];
labelLevel.text = [NSString stringWithFormat:@"%d",self.レベル];
[baseView addSubview:labelLevel];

UILabel* labelTaikyu = [[UILabel alloc] initWithFrame:CGRectMake(105, 230, 30, 20)];
labelTaikyu.text = [NSString stringWithFormat:@"%d",self.耐久];
[baseView addSubview:labelTaikyu];

UILabel* labelSoko = [[UILabel alloc] initWithFrame:CGRectMake(105, 253, 30, 20)];
labelSoko.text = [NSString stringWithFormat:@"%d",self.装甲];
[baseView addSubview:labelSoko];

UILabel* labelKaihi = [[UILabel alloc] initWithFrame:CGRectMake(105, 276, 30, 20)];
labelKaihi.text = [NSString stringWithFormat:@"%d",self.回避];
[baseView addSubview:labelKaihi];

UILabel* labelTosai = [[UILabel alloc] initWithFrame:CGRectMake(105, 299, 30, 20)];
labelTosai.text = [NSString stringWithFormat:@"%d",self.搭載];
[baseView addSubview:labelTosai];

UILabel* labelSokuryoku = [[UILabel alloc] initWithFrame:CGRectMake(95, 322, 40, 20)];
labelSokuryoku.text = self.速力;
[baseView addSubview:labelSokuryoku];

UILabel* labelShatei = [[UILabel alloc] initWithFrame:CGRectMake(105, 345, 30, 20)];
labelShatei.text = self.射程;
[baseView addSubview:labelShatei];

UILabel* labelKaryoku = [[UILabel alloc] initWithFrame:CGRectMake(197, 230, 30, 20)];
labelKaryoku.text = [NSString stringWithFormat:@"%d",self.火力];
[baseView addSubview:labelKaryoku];

UILabel* labelDenso = [[UILabel alloc] initWithFrame:CGRectMake(197, 253, 30, 20)];
labelDenso.text = [NSString stringWithFormat:@"%d",self.雷装];
[baseView addSubview:labelDenso];

UILabel* labelTaiku = [[UILabel alloc] initWithFrame:CGRectMake(197, 276, 30, 20)];
labelTaiku.text = [NSString stringWithFormat:@"%d",self.対空];
[baseView addSubview:labelTaiku];

UILabel* labelTaisen = [[UILabel alloc] initWithFrame:CGRectMake(197, 299, 30, 20)];
labelTaisen.text = [NSString stringWithFormat:@"%d",self.対潜];
[baseView addSubview:labelTaisen];

UILabel* labelSakuteki = [[UILabel alloc] initWithFrame:CGRectMake(197, 322, 30, 20)];
labelSakuteki.text = [NSString stringWithFormat:@"%d",self.索敵];
[baseView addSubview:labelSakuteki];

UILabel* labelUn = [[UILabel alloc] initWithFrame:CGRectMake(197, 345, 30, 20)];
labelUn.text = [NSString stringWithFormat:@"%d",self.運];
[baseView addSubview:labelUn];

UIView* quickLookView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 487, 374)];
[quickLookView addSubview:baseView];

return quickLookView;
}

custom

なんだかここまでくると、だんだんなんのためのデバッグなのかわからなくなってくるんですけど、ま、わかりやすいデバッグ情報は重要ですよね! 内部構造が複雑なクラスでは実装しておいても損はないかもしれません。

ソースコードはGitHubにあります。

Link