忍者ブログ

Home > > Macアプリを作ろう―より良いユーザビリティの為に。

[PR]

  • 2017-03-29

Share on Tumblr このエントリーをはてなブックマークに追加

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Comments:

さぶちゃん 2012-06-19 (火) 13:32

丁寧に説明しているのはいいのですが、細かく刻みすぎて、そこで自己完結されているので、正直さっぱりわかりませんでした。 実際、この通りコードを入力したつもりですが、バグってテーブルの表示ができません。

通常なら、ここでサンプルのソースコードを見合わせて、自分がどこで間違ったが理解していうのですが、わざとソースは公開しないという、最後にいきなり殿様状態で憤りを感じました。 

どこか、自分はすごいんだせ〜!、でも教えてやんない!っというように感じられて仕方がありません。

tnantoka 2012-06-19 (火) 20:31

コメントありがとうございます。
せっかく最後まで試していただいたのに不快な思いをさせてすみませんでした。

ソースに関しては非公開にするメリットは特にないということがわかったので、
以下で公開しております。もし宜しければご利用ください。
https://github.com/tnantoka/ColorClick

また、文章力等がいたらず、わかりづらい説明になって申し訳ありません。
もっと数をこなしてスキルをあげたいと思います…。

フィードバックありがとうございました。

さぶちゃん 2012-06-19 (火) 23:22

すいませんでした。 数時間かけてやっと見つけた、cocoaでのツールのサイトでしたので、いくら最初から試してみてもうまくいかず、テンションが上がってしまってケチをつけてしまいまして申し訳ありませんでした。
文頭での何故いま,cocoa なのかにたいへん共鳴して、感動した分、その反動が大きかったものでしたので・・・

今回のブログも4つくらい(色をピックする、テーブルに表示する、10進数にする、広告をいれる)にわけて日割りで更新していただいたほうが、魅力的だと思います。 短いと、なんとなく出来そうな気持ちになるので、試したくなります。 他のブログあるように、そのポイントまでのサンプルコードにしていただくと、これが大変勉強になります。 他の事を気にせずにその日のテーマだけに要点をしぼれるので何を中心にコードを読むか明確になります。

個人的な感想ですが、このように小分けして更新しているブログは、何度も後になって見に行っています。 一気にまとめて全コードをのせているブログは、いきなりものすごく高い壁にぶつかった感じで、読む前に諦めてしまいます。

iphoneに関するブログは無限と言っていいほどありますが、cocoa を扱ったブログは、海外でもほとんどありませんでした。もっとも、今まではmac上でしか動かないツールは、意味が無いという感じでしたが、iphoneの登場で今だからこそmacのツールが必要だと考えています。 ゲームを作りたければ、データの加工や、アニメーション付け、あたり判定を付けるツールが必要になってきますが、いくらiphoneのコードが組めても、mac用のコードは組めないと実感しています。 その理由として、書籍、文献がほとんどないということでしょうか。 例えば、ipohneで、GLを使ってスプライトアニメーションををさせるには、書籍や、ネットのサンプルコードを元に、簡単にできますが、同じ事をmacでさせようとすると、さっぱり判らないという具合です。

あくまで個人的な予測ですが、今回のようなmac向けのツール開発のレクチャーを掲載されていくと、注目されていくと考えています。 (旧)cocoaの日々は、以前は余り興味がなかったのですが、本格的にiphoneアプリを開発していこうとすると、最終的には、如何にツールを準備して作業効率を図るかになってきます。 いまでは、ここのラバーバンドのブログは涙ものになるくらい参考にしてます。

大変失礼な書き込みのうえに、持論まで書き綴りましたが、今だからこそcocoaという考えは本当に素晴らしいことだと思います。 ケチをつけながら、こういうとふざけたようになりますが、今後の活動を期待しています。

tnantoka 2012-06-20 (水) 12:08

再度ご訪問、及び、ありがたいコメントありがとうございます。

「長すぎる」というのはまさに仰るとおりで、小分けにすればよかったなと何度も後悔しました。
次回以降はもっと小さなテーマに絞って書きたいです…。

Macアプリに関する日本語情報は(なぜか)まだまだ少ないので、
もっと情報発信して、国産アプリの増加に貢献したいと思います。

今後とも宜しくお願いします。

ha 2012-07-28 (土) 23:50

通りすがりの者です。
コメント読ませていただきました。
読者のクレームコメントに真摯に対応する姿勢には頭が下がります。

ho 2012-07-29 (日) 00:24

通りすがりの者です。追記です。
MACアプリ開発に関する情報はほんとにすくないですね。
なるべく簡素にMACアプリをコーでリングし、APPファイルまで作るという一連の流れを
説明してもらって、非常に助かります。

途中の説明文で必要なソースの記述あれば、
最終的なソースをあえてしないという姿勢は、わたしには良くわかります。
その方が、読み手の自分の問題解決能力が鍛えられます。

貴重な情報を無料で読ませてもらった上に自分本位のクレームを付けるのは
とても考えられません。
世の中の読者には、著者は自分のために記事を書いていると誤解する人が少なからずいます。
無意識に女王様状態なのでしょう。

「殿様状態」と女王様読者からののしられているように見えましたw。

ただ、女王様への大人な対応、見習いたいですねw。

Trackback+Pingback:

Listed below are links to weblogs that reference
[PR] from Born Neet

Home > > Macアプリを作ろう―より良いユーザビリティの為に。

Home > Mac App > Macアプリを作ろう―より良いユーザビリティの為に。

Macアプリを作ろう―より良いユーザビリティの為に。

Share on Tumblr このエントリーをはてなブックマークに追加

はじめに

お久しぶりです。

いやぁホントに最近はブログ書けてませんね。
アウトプットが大事なのは理解しているつもりなのですが、どうしても読書やプログラミング自体に時間を使ってしまい、その結果を記事にするのが疎かになってしまいます。

ただ、元々文章を書くのは好きだし、ゆくゆくはそういう物書き的なお仕事も是非していきたいと思ってるので、今年は心を入れ替えて定期的に更新できるように頑張りたいと思います。

というわけで、今日は久々にObjective-Cのお話です。

なお、ウケるブログを書くための21の発想法に、”多くのブログ投稿は、ミニチュアの教科書のようだ。”という言葉があってめっちゃ納得したので、今回は若干チャラい文体になっております。予めご了承下さい。

それでは、始まりまーす。

※ 「続きへ」は嫌いなので基本やらないんですが、今回長文になりすぎたのでブログのサイズ制限に引っかかったので途中(前フリと本題)で分けてます、ごめんなさいm(_ _)m 全文はこちらにあります

なぜ、今macアプリなのか。

皆さんはEvernoteやDropbox、使ってますか?
使ってますよね、僕もとてもお世話になっています。

では、evernote.comやdropbox.comにアクセスしてますか?
…あまりしてませんよね。
せいぜい他の人のコンピュータで作業しなきゃいけない時ぐらいでしょうか。

つまりはそういうことだと思います。

HTML5や第2次ブラウザ戦争等によってクライアントJavaScriptはすごい速度で発展しています。
しかし、当然ながらネイティブアプリに追いつくのはまだまだ先でしょう。

僕自身もJS出身のプログラマですから、Web技術で全てを書けるのが理想ではあります。
しかし、ユーザにとってそんなことは関係ありません。

少なくとも現時点で、より使いやすいものを提供するためには、ネイティブアプリのノウハウを積むことの方が近道なんじゃないか、というのが最近の僕の考えです。
(GoogleのNative Clientすげぇってのはありますが、あれも結局Web技術じゃコンテンツ作れないですしね)

ごちゃごちゃ書きましたが、単純に、次作りたいものを考えてた時に、どうしてもBookmarkletかブラウザ拡張の力を借りないといけなくて、UX的にそれはないなぁと諦めてMacアプリの勉強を始めたという次第です。

pathとかflipboardとかもそうだけど、アプリメインで成り立ってるサービスが流行ってるから洗脳されてるんじゃね、と言えばそうかもしれません。
まぁいずれにせよ自己暗示は大切です。

なんでiOSじゃないの?

個人的なニーズによるものです。
次作りたいと思ってるものが、キーボードをガシガシ打って使うユーティリティツールなので、iOSではやっぱりまだ厳しい。

あと、入門記事的な観点で言うと、Objective-C初心者にはmacアプリの方がお勧めできると思っています。
というのも、macアプリは、iOSシミュレータを挟まない分、コンパイルから実行までが早くて開発がスムーズです。そして、シミュレータ絡みのわけわからんエラーに悩まされなくても済みます。

それに、App Storeを経由しなくても自由に配布できるので、公開のハードルが(金銭的な面も含めて)ぐんと下がるというメリットもあります。

今日作るもの

ソフトウェア開発に欠かせない、カラーピッカー(スポイトツール)を作ります。

macには標準で“DigitalColor Meter”というソフトが付属していますが、なぜかLionになってから、16進数表示が削られてしまったのです。
Mac App Storeに色々あるけど有料が多いし、無料のはイマイチ使い勝手がよくありません。
そんなに真面目に探してないので良いアプリもあるのかもしれませんが、なぜデスクトップ上にある色を知りたいだけなのにそんな手間をかけなきゃいけないんでしょうか。

「文句があるならお前が作れば?※1

全くですね。じゃあ作りましょう。

※1 余談ですが、(特に日本の)エンジニア達は、いざとなったらこの言葉を言う資格がある、ということを胸に留めておくべきではないでしょうか。ものづくりをできるあなた達は、もっと偉いはずです。

まずは名前から

名前が決まらないとXcodeのプロジェクト名が決められません。
この名前はクラス名とかにも使われちゃうので後で変えるのは大変面倒です。

今回はマウスで色を取得するアプリなので、これらに関連する単語から名前を考えてみます。

適当で良いのでダジャレで、かつ、そうですねぇ、最近和の響きが好きなので…
…ColorClick、略して、“カラクリ”にしましょう。

予習と環境

私は以下の本で学習しました。
(アフィリエイトリンクが嫌な人はぐぐってね☆)

photo
Mac OS X Cocoaプログラミング 第三版
Aaron Hillegass アーロン ヒレガス 村上 雅章
ピアソン桐原 2009-11-01

by G-Tools , 2012/01/29

といっても、初めの50ページぐらいこそコードを打ちながら真面目にやりましたが、途中から飽きて流し読みしました。まぁその程度です。
なお、原著は既に第4版が出版されていますので、英語を読める人はCocoa Programming for Mac OS Xを購入する方が、安いし情報も新しくて良いでしょう。(当然、Kindleならもっと安いです)

環境は、Mac OS X 10.7.2、Xcode 4.2.1です。
Xcodeが入っていない人は、Mac App StoreからXcodeをダウンロードして、Install Xcodeを実行して下さい。(XcodeはDL→Installと何故か2段階になっています。)
※ バージョン4.3から、直接インストールされる構成に変更になったようです。なお、サンプルは4.3でもBuildできることを確認しています。(2012/3/6 追記)

なお、Macアプリに使うフレームワークはCocoaといいます。
開発中は特にCocoaという名前を意識しませんが、ハマった時に、Cocoaという単語を入れて検索したほうが引っかかってきやすかったりするので覚えておいて下さい。
(ちなみにiOSの開発にはCocoa Touchを使います。)

プロジェクトの作成

毎度のことながら前フリが長くてごめんなさい!
ようやく実作業に入ります。

Xcodeを起動して、Welcome画面から、Create a new Xcode projectを選択。


左ペインのMac OS XからApplicationをクリック、右ペインでCocoa Applicationを選択してNextをクリックします。


次の画面では、アプリケーションの情報を設定します。
Product NameにはColorClick
Company Identifierはドメインを逆順にしたもの(com.bornneet等)を、
Class PrefixはCC
App Store CategoryはGraphics Designにしておきましょう。
チェックボックスは全て外して、Nextをクリックします。


そうすると、保存ダイアログが出るので、
Create local git repository for this projectをチェックして、
Createをクリックします。

(gitリポジトリは任意ですが、作っておくとソースのバージョン管理ができ、特定のバージョンに戻したりといったことが簡単にできるようになります。使い方がわからなくても大きな変更の前後にメニューからFileSource ControlCommitしておけば救われることがあるかもしれませんよ。)

これで無事プロジェクトが作成されました。
では早速、左上の▶Runボタンを押してみましょう。

なんと何もコードを書いてないのに空のウィンドウを持ったアプリが実行されました。
素晴らしいですね!

半透明のウィンドウを表示する

カラーピッカーと言えば、半透明の黒いウィンドウが常に最前面にあるイメージです。

人間もアプリも見た目が全てではないですが、非常に大切なファクターではあります。
開発のモチベーションのためにも、まずは、それっぽい見た目にしてみましょう。

インターネットにはいろいろと古い情報もあって、結構面倒くさいんだなぁと萎えていたら、 (旧) Cocoaの日々: HUDを探して... に簡単な方法が載っていました。
xcatsanさんのブログはcocoaの情報満載で勉強になりまくるので是非チェックしてみて下さい。

それでは、手を動かしていきましょう。

Xcodeの左端のProject navigatorから、MainMenu.xibをクリックします。
するとGUIの編集画面(Xcode3までは“Interface Builder”として別アプリになっていたもの)に入りますので、
真ん中辺りのObjectsのWindow - ColorClickを選択しておきます。
そして、右下のObject Libraryから、HUD Window※2をドラッグ&ドロップで適当な位置に配置しましょう。
ObjectsにPanel - Windowが追加されます。


デフォルトだと、ウィンドウの座標やサイズがアプリケーションを終了するたびにリセットされてしまうので、右端のAttribute Inspectorから、WindowのAutosaveにColorWindow等と入力しましょう。

ここまで終わったらアプリケーションを実行してみてください。
サイズや位置が保存される半透明のウィンドウが表示されるはずです。


あと、タイトルがWindowになってしまっていて残念なので、Attribute InspectorでTitleを消しておきましょう。

※2 HUD WindowはNSPanel(NSWindowのサブクラス)なので、普通のウィンドウと挙動が違うのですが、今回はこれを使う前提で進めます。

ウィンドウの削除と再表示

現状だと、ColorClickというタイトルのウィンドウも表示されていますが、これはいらないので、
Interface Builder(以降IB)のObjectsからWindow - ColorClickを選択してdeleteキーで削除しましょう。


この状態で実行すれば半透明なウィンドウだけのおしゃれなアプリケーションになります。

ただ、このままだと重大な問題があります。
…そう、左上の×ボタンを押してウィンドウを閉じた後、Dockアイコンをクリックしてもウィンドウが再表示されないのです。
これは最悪ですね。

最も簡単な解決策は、Attribute Inspectorで半透明ウィンドウ(以降Panel)のCloseのチェックを外すことです。
これでウィンドウを閉じることができなくなります。

しかしこれはイマイチなので、少し頑張ってみたいと思います。
といっても少しの作業とコードで解決します。

まずは半透明ウィンドウをプログラムから操作できるようにOutletを設定します。
IBのObjectsで、controlキーを押しながらApp Delegateをクリックします。
すると以下のような画面が出てきます。


そうしたら、Outletsのwindowの右にある(マウスを持って行くとが表示されます)をドラッグ&ドロップしてPanelと接続して下さい。


この作業では、CCAppDelegate.hに、

@property (assign) IBOutlet NSWindow *window;

として定義されている変数(プロパティ)にPanelを紐付けています。
これに加えて、CCAppDelegate.mに以下のコードが書かれていることで、プログラム内からself.windowとして参照可能になります。(実は、先程削除したグレーのwindowが、元々このプロパティに接続されていました。)

@synthesize window = _window;

それではDockがクリックされた時にウィンドウを再表示するようにしましょう。
これは、CCAppDelegate.m

- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
    // windowを前面に
    [self.window makeKeyAndOrderFront:nil];
    return NO;
}

というメソッドを定義すればOKです。

あとはウィンドウを閉じた時にインスタンスが解放されないように、IBのAttribute Inspectorから、PanelのRelease when closedのチェックを外しておきましょう。(これを忘れると解放されて既に存在しないPanelを再表示しようとして、アプリケーションが落ちます…。)
ここまでできたらアプリケーションを実行してみて下さい。
ウィンドウを閉じた後にDockのアイコンをクリックすると再表示されるはずです。

マウスの座標を取得する

いよいよメインの機能に関わる部分ですね。
まずは現在のマウスカーソルがある座標を取得してみます。

アプリの特性上この処理は、他のアプリケーションを操作中でも、マウスが動くたびに自動で行う必要があります。
これは、[NSEvent addGlobalMonitorForEventsMatchingMask:handler:を使えば簡単に実現できます。
(参考:日暮れて道遠し: ユニバーサルアクセスの補助装置にアクセスできるようにする

そして、肝心の座標ですが、CGEventGetLocationで左下原点の座標が取得可能です。

それでは実装します。
本来はクラスを適切に分割すべきですが、今回は簡略化の為、全てCCAppDelegate.mに書いていきます。それではまず、アプリケーションの起動時に実行されるapplicationDidFinishLaunching:メソッド内に以下を追記します。

// マウスが移動したら…
[NSEvent addGlobalMonitorForEventsMatchingMask:NSMouseMovedMask handler:^(NSEvent *event) {
    // 自分のglobalMouseMoved:を呼ぶ
    [self globalMouseMoved:event]; 
}];

このコードはマウスが移動するたびに、globalMouseMoved:というメソッドを呼ぶという意味です。
では次に呼ばれるメソッドを書いていきます。

メソッドの中身を書く前に、#import "CCAppDelegate.h"@implementation CCAppDelegateの間に以下を記述してメソッドを宣言します。(なくても動きますがエラーが出ますので書いておいた方が良いでしょう。また、CCAppDelegate.hでも宣言できますが、他のクラスから呼ばれないメソッドの場合は今回の書き方でOKです。)

@interface CCAppDelegate()
- (void)globalMouseMoved:(NSEvent *)event;
@end

つづいて、メソッドの中身を定義します。

- (void)globalMouseMoved:(NSEvent *)event {
    // 左下原点のマウス座標を取得
    CGEventRef eventRef = CGEventCreate(NULL);
    CGPoint point = CGEventGetLocation(eventRef);
    // CGEventRefの解放
    CFRelease(eventRef);
    // ログ表示(動作確認用)
    NSLog(@"globalMouseMoved: x = %f, y = %f", point.x, point.y);
}

この状態でアプリケーションを実行すると、他のアプリケーションの操作中、マウスが移動するたび、XCode下部のDebug Areaに、

2012-02-06 22:22:33.537 ColorClick[18558:707]
globalMouseMoved: x = 1073.113281, y = 829.394531
2012-02-06 22:22:33.553 ColorClick[18558:707]
globalMouseMoved: x = 1074.160156, y = 830.437500

といったログが出力されるようになります。

画面キャプチャ

マウスの座標が取得できたので、次はその位置の色を取得すれば良さそうです。
しかし、いかに高機能なCocoaでもそんな便利メソッドはありません。(おそらく)

ただ、その周辺の情報が画像データとして手に入ればあとは解析すればなんとかなりそうな気はします。

というわけでマウスカーソル周辺の画面キャプチャを撮ってみましょう。
これはCGWindowListCreateImageを用いて実装できます。
(参考:(旧) Cocoaの日々: 画面キャプチャその6 - 選択範囲をキャプチャ(完成)

まずは、キャプチャした画像を表示するパーツを作成します。
IBでImage WellをPanelに追加します。
そのままだと少しダサイので、Attribute InspectorでBorderをGrooveに変更します。
また、ScallingはProportionally Up or Down(Image Wellに合わせて拡大縮小される)に設定。
あとは、Size Inspectorで、Width・Heightを共に77にしておきましょう。(プログラミングの都合上11の倍数に)


次にプログラム上から操作できるようにOutletを設定します。
Xcode右上のEditorからAssistant Editor(蝶ネクタイ?アイコン)を選択します。
すると右側にコードエディタが表示されますのでCCAppDelegate.hを表示しておきましょう。

この状態で、先程追加したImage Wellから、controlキーを押しながら@endの上辺りまでドラッグドロップすると以下の画面が表示されますので、imageViewと入力してConnectをクリックして下さい。
これでプログラムから、self.imageViewとして参照できます。


最後に、globalMouseMoved:に以下のコードを追加します。(Editorは必要に応じてStandardに切り替えて下さい)

// キャプチャサイズ
int size = 11;
// 真ん中の座標
int center = floor(size / 2.0);
// マウス座標を中心にした矩形を作成
CGRect captureRect = CGRectMake(point.x - center, point.y - center, size, size);
// 画面キャプチャ
CGImageRef cgImageRef = CGWindowListCreateImage(captureRect, 
    kCGWindowListOptionOnScreenOnly, kCGNullWindowID, 
    kCGWindowImageBoundsIgnoreFraming);    
// 表示するためにNSImageを作成
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:cgImageRef];
NSImage *image = [[[NSImage alloc] init] autorelease];
[image addRepresentation:bitmap];    
// Image Wellに設定
self.imageView.image = image;

アプリケーションを実行してみましょう。良い感じですね!

(Panelが非アクティブな時しかうまく動作しないですが、妥協します)

画像からRGB値取得

必要な材料は揃ったので、画像を解析してRGBを取得します。
CGImageGetDataProviderCGDataProviderCopyDataCFDataGetBytePtrを使えば、先程キャプチャで得たCGImageRefから、ビットマップデータの配列を取得することができます。
(参考:【コラム】実践! iPhoneアプリ開発 (4) カメラアプリの作り方 (4) - 写真にエフェクトをかける | エンタープライズ | マイナビニュース

ではインタフェースから整えていきます。
MainMenu.xibを選択してIBを開きます。
まずは、Boxを追加して、Attribute InstectorでBox TypeをCustom、Border TypeをNone、Fill ColorをWhiteに設定します。サイズは適当な正方形にして右上に配置します。(このBoxの背景色を変更して取得したRGBを表示します。)
次にLabelは、Alignmentを右寄せ、Text ColorをWhite、Widthは130ぐらいにしてBoxの下に追加します。
(このLabelにはテキスト形式でRGBを表示します。)

あとは、どこの色を取得しているかわかりやすくするため、Image Wellの真ん中に7x7の白い枠だけのBoxを置いておくと良いでしょう。
さらにPanelのサイズも横250x縦400ぐらいに縮小しておきます。

このようになります。


次はプログラムから操作可能なように、右上のBoxをcolorBox、LabelをcolorLabelとしてOutlet設定します。
Assistant Editorを表示し、controlキーを押しながら、CCAppDelegate.hのコード内にドラッグ&ドロップしてConnectしましょう。


最後にコードですが、今回は画像の真ん中の座標のRGBだけがあれば良いので、以下のように実装しました。

キャプチャを11x11で取得しているので、座標x=5、y=5(キャプチャ時にcenterという変数に入れておいたもの)のRGB値を取得しています。
なおビットマップの並びがBGRAになっているので注意して下さい。
(参考:CoreGraphicsでハマる - 定食屋おろポン

// CGImageRefからビットマップデータを取得
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImageRef);
CFDataRef data = CGDataProviderCopyData(dataProvider);
UInt8* buffer = (UInt8*)CFDataGetBytePtr(data);
size_t bytesPerRow = CGImageGetBytesPerRow(cgImageRef);    
// 中心のビットマップを取得
int x = center;
int y = center;    
UInt8 *index = buffer + x * 4 + y * bytesPerRow;    
// BGRA
UInt8 r = *(index + 2);
UInt8 g = *(index + 1);
UInt8 b = *(index + 0);
// Boxの背景色、Labelのテキストを設定
self.colorLabel.stringValue = [NSString stringWithFormat:@"#%x%x%x", r, g, b];
self.colorBox.fillColor = [NSColor colorWithDeviceRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];

それでは実行してみます。

Goodですね。

クリックした色の履歴表示

ここまでで難しい部分は終わったので、あとはアプリが便利になるように機能を追加していきます。

まずは、クリックした場所の色を、表形式で履歴表示してみたいと思います。
カラーピッカー系のアプリって、その瞬間の色しかとれなくって不便なこととかあるので。

それではUIから。
IBでPanelにTable Viewを追加します。 Size InspectorでScroll View - Table…の幅を210、高さを170に設定し、続いて、Attribute InspectorでTable ViewのHeadersのチェックを外し、Grid StyleをHorizontal、Grid ColorをWhite、BackgroundをBlack、Focus RingをNoneにします。
TableColumnの1列目は、Identity InspectorでIdentifierを0にして、MinimumとWidthを20にし、中のText FieldのDraws Backgroundをチェック。 2列目は、Identifierを1にし、Text FieldのText ColorをWhiteにします。幅は180ぐらいに広げておきます。

なお、TableViewはプログラムから操作するため、tableViewとしてOutlet接続しておきましょう。
(誤ってScroll Viewを接続しないように注意!)


また、履歴が増え続けると困るので、削除ボタンも付けましょう。
Push ButtonをPanelに追加して、TitleをClearに変更すればOKです。

ここまでの作業でインタフェースはこのようになります。


それではクリック時の処理を実装していきます。

CCAppDelegate.hitems_という履歴を保持する配列と、現在の色を保持するred_green_blue_という変数を追加します。
また、TableView関連の処理を実装することも宣言するため、, NSTableViewDataSource, NSTableViewDelegateという記述もしておきます。

@interface CCAppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate> {
    NSMutableArray *items_;
    UInt8 red_;
    UInt8 green_;
    UInt8 blue_;
}

配列はapplicationDidFinishLaunching:の中で初期化します。

items_ = [[NSMutableArray array] retain];

アプリケーション終了時に解放する処理も忘れずに追加します。

- (void)dealloc
{
    [items_ release];
    [super dealloc];
}

それではマウスクリック時にitems_に要素を追加してみましょう。

まず、今表示されている色の情報が欲しいので、globalMouseMoved:の末尾にred_green_blue_への代入処理を追加します。

red_ = r;
green_ = g;
blue_ = b;

クリックはマウス移動と同じく自分のアプリの外にある時に処理できるように、addGlobalMonitorForEventsMatchingMask:handler:を使います。

[NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask handler:^(NSEvent *event) {
    [self globalMouseDown:event]; 
}];

globalMouseMoved:と同じく、ファイル冒頭でメソッドの宣言も追加しておいて下さい。

次に、追加するデータ、つまりitems_の1要素ですが、[RGBのテキスト値(#rgb), NSColorオブジェクト]という配列にします。
つまり0個目の要素が白なら、
items[0][0]がテキスト情報(#ffffff等)、
items[0][1](最後の要素)が白を表すNSColorオブジェクトになります。

クリックのたびにこのデータを作成し、新しいものが上に来るように0番目に挿入します。 ただし、前回と同じ色なら追加しないほうが親切なので、items_が1個以上あれば0番目と比較して同じでない場合のみ処理します。

これらを踏まえて実装したglobalMouseDown:は以下のようになります。

- (void)globalMouseDown:(NSEvent *)event {
    // 自分がアクティブか非表示なら何もしない
    if ([self.window isKeyWindow] || ![self.window isVisible]) {
        return;
    }
    // RGBの16進数文字列
    NSString *hex = [NSString stringWithFormat:@"#%x%x%x", red_, green_, blue_];
    // NSColorオブジェクト
    NSColor *color = [NSColor colorWithDeviceRed:red_/255.0 green:green_/255.0 blue:blue_/255.0 alpha:1.0];
    // 直前の色と同じじゃない場合のみ追加
    if (items_.count == 0 || !([[[items_ objectAtIndex:0] lastObject] isEqualTo:color])) {
        // [16進文字列, NSColor]という配列データを挿入する
        NSArray *item = [NSArray arrayWithObjects:hex, color, nil];        
        [items_ insertObject:item atIndex:0];
    }    
    // TableViewを更新する
    [self.tableView reloadData];
}

そして、TableViewにこのitems_の内容を表示するようにします。
2列目はテキストでRGBを表示し、1列目は背景にそのRGBで色をつけます。
これはそんなに難しくなく、以下の3メソッドを実装するだけです。

// TableView関連の処理
#pragma mark TableView
// TableViewの行数
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    // つまりitems_の要素数
    return items_.count;
}
// TableViewの表示内容
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // 何列目か
    switch ([tableColumn.identifier intValue]) {
        // 2列目(Identifierが1)はitems_[raw][0]を表示
        case 1:
            return [[items_ objectAtIndex:row] objectAtIndex:0];
            break;            
        // その他は(1列目も)表示内容無し
        default:
            return @"";
            break;
    }
}
// TableViewの表示直前に呼ばれる
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // 1列目なら
    if ([tableColumn.identifier isEqualToString:@"0"]) {
        // 背景色をitems_[raw][last]に
        [cell setBackgroundColor:[[items_ objectAtIndex:row] lastObject]];
    }
}

上記メソッドが呼ばれるように、applicationDidFinishLaunching:でTableView関連の各種処理と表示データの管理をCCAppDelegate(self)が担当するということを設定しておきます。

self.tableView.dataSource = self;
self.tableView.delegate = self;

最後にクリアボタンです。
Assistant Editorで、Buttonからcontrolキー+D&Dし、clearItemsとしてActionに接続します。
(OutletではなくActionなので注意)


これでボタンをクリックした時にclearItems:メソッドが呼ばれます。
メソッド内の処理は単純で、items_内を全削除し、TableViewを更新するだけです。

- (IBAction)clearItems:(id)sender {
    [items_ removeAllObjects];
    [self.tableView reloadData];    
}

それでは実行してみましょう。

おぉ、アプリっぽくなってきましたね!

表示形式切り替え

大事な機能を忘れてました。
このままでは16進数しか使えませんので、他のアプリに負けてしまいます。
10進数でも表示できるようにしましょう。

まずは、IBでPanelの右下にPop Up Buttonを追加します。
次に、ObjectsからPop Up Buttonを選択し、Pop Up Button CelMenu - Other…とたどっていき、3つあるMenu Item…の最後を削除します。
そして、Attribute Inspectorで1つめのTitleを16進数を表す#rgbにしてState(チェック)をOnに、2つめのTitleは10進数を表すrgb()にしておきます。

こうなります。


それでは表示形式の切り替え処理を実装します。

Pop Upが変更された時に処理する為に、Actionを接続しましょう。
Assistant Editorでcontrolキーを押しながらCCAppDelegate.hを表示したエディタにD&Dし、changeColorFormatと入力してConnectをクリックします。


また、Pop Up Buttonはプログラムから選択状態を参照したいのでpopUpとしてOutletも接続しておきます。


changeColorFormat:は以下のようになります。

// Pop Up Button変更時に呼ばれる
- (IBAction)changeColorFormat:(id)sender {
    // 現在の状態を設定ファイル(NSUserDefaults)に保存
    [[NSUserDefaults standardUserDefaults] setInteger:[sender indexOfSelectedItem] forKey:@"ColorFormatIndex"];
    // TableViewを更新
    [self.tableView reloadData];
}

選択状態はアプリを終了しても保持しておきたいので、NSUserDefaultsを利用して設定ファイルに保存しています。
また、アプリ起動時には保存した選択状態をPop Upに反映させる必要があるので、applicationDidFinishLaunching:に以下のコードを追加します。

// 設定ファイルに選択状態が保存されていたらPop Upに反映する
NSInteger index = [[NSUserDefaults standardUserDefaults] integerForKey:@"ColorFormatIndex"];
if (index) {
    [self.popUp selectItemAtIndex:index];        
}

最後に選択状態に応じて表示を切り替えます。
まず、globalMouseMoved:でLabelの文字列を設定している部分を変更します。

/* [変更前] */
    //self.colorLabel.stringValue = [NSString stringWithFormat:@"#%x%x%x", r, g, b];
/* [変更後] */
    if ([[NSUserDefaults standardUserDefaults] integerForKey:@"ColorFormatIndex"] == 1) {
        self.colorLabel.stringValue = [NSString stringWithFormat:@"rgb(%d, %d, %d)", r, g, b];
    } else {
        self.colorLabel.stringValue = [NSString stringWithFormat:@"#%x%x%x", r, g, b];
    }

これで、Labelの表示が切り替わります。

次にTableViewの為に、items_に保持するデータを[16進, 10進, NSColorオブジェクト]に変えます。 globalMouseDown:を以下のように変更して下さい。

- (void)globalMouseDown:(NSEvent *)event {
    // 自分がアクティブなら何もしない
    if ([self.window isKeyWindow]) {
        return;
    }
    // RGBの16進数文字列
    NSString *hex = [NSString stringWithFormat:@"#%x%x%x", red_, green_, blue_];

/* [追記ここから] */
    // RGBの10進数文字列
    NSString *decimal = [NSString stringWithFormat:@"rgb(%d, %d, %d)", red_, green_, blue_];
/* [追記ここまで] */

    // NSColorオブジェクト
    NSColor *color = [NSColor colorWithDeviceRed:red_/255.0 green:green_/255.0 blue:blue_/255.0 alpha:1.0];
    // 直前の色と同じじゃない場合のみ追加
    if (items_.count == 0 || !([[[items_ objectAtIndex:0] lastObject] isEqualTo:color])) {

/* [変更ここから] */
        // [16進文字列, 10進文字列, NSColor]という配列データを挿入する
        NSArray *item = [NSArray arrayWithObjects:hex, decimal, color, nil];        
/* [変更ここまで] */

        [items_ insertObject:item atIndex:0];
    }    
    // TableViewを更新する
    [self.tableView reloadData];
}

そして、表示の際はNSUserDefaultの値を用いてitems_からデータを取り出します。
つまり0番目が選択されていたらitems_[n][0]なので16進数、
1番目が選択されていたらitems_[n][1]なので10進数を表示できるというわけです。
コードは以下のようになります。

// TableViewの表示内容
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // 何列目か
    switch ([tableColumn.identifier intValue]) {
        // 2列目(Identifierが1)はitems_[raw][0]を表示
        case 1:
/* [変更ここから */
            return [[items_ objectAtIndex:row] objectAtIndex:[[NSUserDefaults standardUserDefaults] integerForKey:@"ColorFormatIndex"]];
/* [変更ここまで */
            break;            
        // その他は(1列目も)表示内容無し
        default:
            return @"";
            break;
    }
}

ちなみに背景表示の方はlastObjectを使っているのでコードを変更する必要はありません。(出来レースですけどね^^)

それではアプリケーションを実行してみます。
起動したらPop Upを切り替えて見てください。

無事、10進数表示ができました。

クリップボードにコピー

今の状態でも、セルをクリックした後少し時間をおいてクリックすれば編集モードになりコピーが可能ですが、さすがにこれは使いづらいです。
TablewViewダブルクリックした時に該当行のテキスト情報をコピーするようにしましょう。
applicationDidFinishLaunching:に以下のコードを追加し、ダブルクリック時に、[self pasteToClipBoard]を呼び出すように設定します。
pasteToClipBoardglobalMouseMove:globalMouseDown:同様に別途宣言も追加しておきます。)

self.tableView.target = self;
self.tableView.doubleAction = @selector(pasteToClipBoard);

コピーはNSPasteboardというクラスを用いて行います。
pasteToClipBoardは以下のようになります。

// TableViewダブルクリック時に呼ばれる
- (void)pasteToClipBoard {
    // クリックされたrowのRGB値を文字列としてPasteboardにコピーする
    NSPasteboard *pb = [NSPasteboard generalPasteboard];
    [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
    [pb setString:[[items_ objectAtIndex:self.tableView.clickedRow]  objectAtIndex:[[NSUserDefaults standardUserDefaults] integerForKey:@"ColorFormatIndex"]] forType:NSStringPboardType];
}
それでは実行してみてください。ダブルクリックするとコピーされることが確認できると思います。
簡単ですね。 (画面キャプチャは伝わらないので割愛します。)

広告

そろそろ大詰めです。

無料で配るアプリだってちょっとぐらいお小遣いになったほうが嬉しい。というわけで広告を貼りたいというのが自然な流れではあります。
…が、てっきりAdMobとかがやってると思ってたら、Mac用は全然無料のサービスがないんですね。

かろうじてBuySellAds.comがやってるらしいんですが、審査とか必要だし、そもそも日本に対応してるかよくわかりませんでした。
(参考:iphone - How to put ads in apps for Mac App Store? - Stack Overflow
悔しいですが、今回はとりあえず適当なViewを表示しておくことにします。

バナーとリンク先はNode.js製のブログエンジンであるLooseLeaf.JSのものにしましょう。

もし本物の広告表示したい人がいたら連絡下さい(笑)

まずlogo.jpgから画像をダウンロードして、Project navigatorのSupporting Filesフォルダにドラッグ&ドロップします。
すると以下の画面が出てきますので、
Copy items into destination group's folder (if needed)にチェックを入れて、Create groups for any added foldersを選択し、Finishしましょう。
これでXcodeのプロジェクト内に画像がコピーされます。


この画像をPanel上に表示します。いろいろ方法はありますが、クリック時の処理が楽にできた方が良いので、ボタンを使うことにします。
IBでSquare Buttonを配置して下さい。Sizeは横を210pxぐらいまで大きくします。
そして、Attribute InspectorからImageをlogoに変更して下さい。
あと、WindowのHeightを小さくすることでせっかくの広告が消せないように、PanelのResizeをOFFにしておきましょう。


続いて、このボタンをクリックした時に、デフォルトブラウザで指定URLを開くようにしましょう。
クリック時の動作ですので、Actionを設定します。
もうお馴染みのAssistant Editor+controlキーD&Dで、CCAppDelegate.hに接続します。
アクション名は、openAdで良いでしょう。


中身は以下のようになります。

- (IBAction)openAd:(id)sender {
    NSURL *url = [NSURL URLWithString:@"http://looseleafjs.org/?utm_source=mac_app&utm_medium=banner&utm_campaign=color_click"];
    // デフォルトブラウザで指定URLを開く
    [[NSWorkspace sharedWorkspace] openURL:url];
}

クエリには万が一広告枠が売れることになった場合に備え、Analytics用の情報を入れておきます。
◯◯件アクセスされてるからこれぐらいで買ってよ、ということですね! (参考:ツール: URL 生成ツール - アナリティクス ヘルプ

では、実行してみましょう。

想定通り、ブラウザが開きました。

アイコン


デフォルトでアイコンがついていますが、これだとDockとかでソフトの判別がしにくい為、オリジナルのアイコンを設定しましょう。

アイコンはネットでフリーの素材やもしくはアイコンそのものを探して加工するのが早いです。
ただ今回は他の人の著作物を入れたくなかったし、Fireworksの使い方を絶賛勉強中なので、適当に作って見ました。
こんな感じです。


サイズ512×512で、形式はpngです。

この画像を、/Developer/Applications/Utilities/にあるIcon Composer.appを用いてアイコン化します。
Icon Composerを起動するとこのような画面になるので、先ほどの画像を左の512と書いてある欄にドラッグドロップします。


以下のようになるので、FileメニューのSave Asでicon.icnsとして保存します。


では設定しましょう。
Project navigator最上部のColorClickを選択し、TARGETSColorClickSummaryタブを選択。
No image specifiedとなっているところに先ほど作成したicon.icnsをドラッグドロップしましょう。
(ColorClick-Info.plistを編集しても設定できます。)


実行してみましょう。

Dockのアイコンが変わりました。

メニューの削除とクレジット表示

仕上げに、必要のないメニュー項目を消してしまいましょう。

IBでメニュー項目を選択してdeleteキーを押せば削除可能です。
それでは、ColorClickのPreferencesServicesとSeparatorを2本、


Fileの、ClosePrint以外を(何も実装しなくても印刷機能がつくのがすごいですね!)、


EditFormatViewWindowHelpは特にあっても便利じゃなさそうなので、項目ごと消しちゃいましょう。
(長期的に拡張するアプリならいつか必要になるかもしれないので、消さないというのもありだと思います。あっても邪魔になるものでもないので)




また、Supporting FilesのCredits.rtfを編集すれば、ColorClickメニューのAbout ColorClickに表示されるクレジット表示を変更できます。
今回は特に書くことないので空にしておきます。

ただ、会社名が、Copyright © 2012年 __MyCompanyName__. All rights reserved.になってしまっていて、あまりにも残念なので、ColorClick-info.plistを修正しておきます。
Copyright (human-readable)をCopyright © 2012 bornneet.com. All rights reserved.に変更します。

こうなります。

日本語化

そう言えば、せっかく思いついたダジャレアプリ名“カラクリ”がどこにも使われてないという悲しい状況です。これはまずいので国際化しましょう。といっても今回はアプリ名だけですが。
(参考:アプリケーションパッケージ名とアプリケーションメニューのローカライズ方法は異なる « Programmer’s High

ColorClick-Info.plistでBundle nameを選択すると横に表示される+をクリックして、Bundle display nameを追加します。ValueはBundle nameのものをコピーして${PRODUCT_NAME}としておきます。




こうすることで、この後設定する言語別のアプリ名が使われるようになります。
では早速設定しましょう。
InfoPlist.stringsのFile Inspectorを見ると、LocalizationがEnglishだけになっているので、+ボタンを押してJapanese (ja)を追加します。


この作業の後、Project navigatorで▶InfoPlist.stringsを開くと、

  • InfoPlist.strings(English)
  • InfoPlist.strings(Japanese)

の2ファイル分かれているので、それぞれ、

CFBundleName = "ColorClick";
CFBundleDisplayName = "ColorClick";
CFBundleName = "カラクリ";
CFBundleDisplayName = "カラクリ";

を追加しましょう。
これでOKです。実行してみると…


メニューとDockのアプリ名が日本語になりました。

パッケージング

いよいよ最後の仕上げです。
まさかユーザにXcodeでBuild & Runしてくれとお願いするわけにはいきませんから、.appファイルにパッケージングします。
これは超簡単です!

XcodeのProductメニューから、Archiveを選択します。
するとOrganizerが開くので、Shareをクリックします。


Contents:はApplicationを選択し、Nextをクリックすると、
保存ダイアログが出てくるのでデスクトップにでも保存しましょう。





これでデスクトップにappファイルができました。



それでは、実行してみましょう。


完成です!!

ダウンロード

完成版のアプリは以下からダウンロードできます。

color_click.zip

まだ荒削りな部分もありますが、入門編のサンプルアプリとしてはちょうどよい規模ではないかと思います。
足りない部分は是非ご自分の手でカスタマイズしてみて下さい。

ソースコード


ソースはあえて公開しません。
あんま意味なさそうだったので公開しました → 以前作ったMac用カラーピッカーアプリ「カラクリ」のソースコードを公開します - tobioka.net

自分で手を動かしながら、ハマったところをコピペで解決していくのはプログラミングのスキルアップにつながりますが、サンプルをそのまま動かしたり、forkするだけでは何の意味もないからです。
僕もこの記事の通り1回試して動作することを確認していますので、特にソースがないとダメなところはないと思います。

あと、配布しているアプリは広告付き版なのでうざいです。
というわけで広告無し版が欲しい人は自分でコーディングするしかない!という新たな取組みです。

プログラミングの勉強を始める時、短期的なゴールが見えづらい。
今回はこのアプリの広告無し版が2〜3時間ぐらいで手に入るはずです!
そして、自分で作れば自由に、例えばピンク色にしたり、背景にあの娘の写真を載せたりとか、いろいろできますしね。

名付けて全Macユーザ、Cocoaプログラマ計画です。是非挑戦してみてください。

最後に

いかがだったでしょうか?
まずはアウトプットを、ということで、いつも以上に浅い部分があったかもしれません。
日本語情報が少ない分野なので誰かの訳に立てば幸いです。
(しばらくMacアプリ系のエントリを投稿すると思うので興味があればまたチェックしてみて下さい)

突っ込み所がありましたら、以下のコメント欄から是非お願いします。(Mail、Facebook、Twetterでも大丈夫です)

記事の長さについては本当にすいません。僕も始めた時はここまで長くなるとは思ってなかったんです…。
単発記事じゃなく連載形式にしておくべきでした。

なお、ライセンスですが、本文部分はCreative Commons (BY-NC)にしときます。(なにげにCC初かも。)
ソースはそれだと使いにくいと思うのでMITで。
誰かiBooks Authorで電子書籍にしてくれないかなー。

1つお願いなんですが、上の趣旨があるので(意味があるかはわかりませんが)、広告を削っただけのカラクリをそのまま配布するのは避けてもらえるとありがたいです。もちろん、自分のアプリの中にコードを使ってもらうのは全然かまいません。

私には無理かも…とか考えている人、そんな暇があったら手を動かしてみましょう!
"Code wins arguments." 作ってみなきゃ何も始まりませんよ。

蛇足

丁寧な文体のほうが読む人はもちろん、書き手にとっても精神的な負担が少ない、ということがわかりました^^

それでは。

Happy Cocoa Programming :-)

PR

Comments:4

さぶちゃん 2012-06-19 (火) 13:32

丁寧に説明しているのはいいのですが、細かく刻みすぎて、そこで自己完結されているので、正直さっぱりわかりませんでした。 実際、この通りコードを入力したつもりですが、バグってテーブルの表示ができません。

通常なら、ここでサンプルのソースコードを見合わせて、自分がどこで間違ったが理解していうのですが、わざとソースは公開しないという、最後にいきなり殿様状態で憤りを感じました。 

どこか、自分はすごいんだせ〜!、でも教えてやんない!っというように感じられて仕方がありません。

tnantoka 2012-06-19 (火) 20:31

コメントありがとうございます。
せっかく最後まで試していただいたのに不快な思いをさせてすみませんでした。

ソースに関しては非公開にするメリットは特にないということがわかったので、
以下で公開しております。もし宜しければご利用ください。
https://github.com/tnantoka/ColorClick

また、文章力等がいたらず、わかりづらい説明になって申し訳ありません。
もっと数をこなしてスキルをあげたいと思います…。

フィードバックありがとうございました。

さぶちゃん 2012-06-19 (火) 23:22

すいませんでした。 数時間かけてやっと見つけた、cocoaでのツールのサイトでしたので、いくら最初から試してみてもうまくいかず、テンションが上がってしまってケチをつけてしまいまして申し訳ありませんでした。
文頭での何故いま,cocoa なのかにたいへん共鳴して、感動した分、その反動が大きかったものでしたので・・・

今回のブログも4つくらい(色をピックする、テーブルに表示する、10進数にする、広告をいれる)にわけて日割りで更新していただいたほうが、魅力的だと思います。 短いと、なんとなく出来そうな気持ちになるので、試したくなります。 他のブログあるように、そのポイントまでのサンプルコードにしていただくと、これが大変勉強になります。 他の事を気にせずにその日のテーマだけに要点をしぼれるので何を中心にコードを読むか明確になります。

個人的な感想ですが、このように小分けして更新しているブログは、何度も後になって見に行っています。 一気にまとめて全コードをのせているブログは、いきなりものすごく高い壁にぶつかった感じで、読む前に諦めてしまいます。

iphoneに関するブログは無限と言っていいほどありますが、cocoa を扱ったブログは、海外でもほとんどありませんでした。もっとも、今まではmac上でしか動かないツールは、意味が無いという感じでしたが、iphoneの登場で今だからこそmacのツールが必要だと考えています。 ゲームを作りたければ、データの加工や、アニメーション付け、あたり判定を付けるツールが必要になってきますが、いくらiphoneのコードが組めても、mac用のコードは組めないと実感しています。 その理由として、書籍、文献がほとんどないということでしょうか。 例えば、ipohneで、GLを使ってスプライトアニメーションををさせるには、書籍や、ネットのサンプルコードを元に、簡単にできますが、同じ事をmacでさせようとすると、さっぱり判らないという具合です。

あくまで個人的な予測ですが、今回のようなmac向けのツール開発のレクチャーを掲載されていくと、注目されていくと考えています。 (旧)cocoaの日々は、以前は余り興味がなかったのですが、本格的にiphoneアプリを開発していこうとすると、最終的には、如何にツールを準備して作業効率を図るかになってきます。 いまでは、ここのラバーバンドのブログは涙ものになるくらい参考にしてます。

大変失礼な書き込みのうえに、持論まで書き綴りましたが、今だからこそcocoaという考えは本当に素晴らしいことだと思います。 ケチをつけながら、こういうとふざけたようになりますが、今後の活動を期待しています。

tnantoka 2012-06-20 (水) 12:08

再度ご訪問、及び、ありがたいコメントありがとうございます。

「長すぎる」というのはまさに仰るとおりで、小分けにすればよかったなと何度も後悔しました。
次回以降はもっと小さなテーマに絞って書きたいです…。

Macアプリに関する日本語情報は(なぜか)まだまだ少ないので、
もっと情報発信して、国産アプリの増加に貢献したいと思います。

今後とも宜しくお願いします。

ha 2012-07-28 (土) 23:50

通りすがりの者です。
コメント読ませていただきました。
読者のクレームコメントに真摯に対応する姿勢には頭が下がります。

ho 2012-07-29 (日) 00:24

通りすがりの者です。追記です。
MACアプリ開発に関する情報はほんとにすくないですね。
なるべく簡素にMACアプリをコーでリングし、APPファイルまで作るという一連の流れを
説明してもらって、非常に助かります。

途中の説明文で必要なソースの記述あれば、
最終的なソースをあえてしないという姿勢は、わたしには良くわかります。
その方が、読み手の自分の問題解決能力が鍛えられます。

貴重な情報を無料で読ませてもらった上に自分本位のクレームを付けるのは
とても考えられません。
世の中の読者には、著者は自分のために記事を書いていると誤解する人が少なからずいます。
無意識に女王様状態なのでしょう。

「殿様状態」と女王様読者からののしられているように見えましたw。

ただ、女王様への大人な対応、見習いたいですねw。

Comment Form

Trackback+Pingback:0

Listed below are links to weblogs that reference
Macアプリを作ろう―より良いユーザビリティの為に。 from Born Neet

Home > Mac App > Macアプリを作ろう―より良いユーザビリティの為に。

Search
Loading
Feeds
Links
スポンサードリンク
Ad
デル株式会社
Ad

Page Top