February 2013

iOS XcodeのStoryboardでTable Viewのカスタムセル

iOSプログラミング、1日取り組んでみて、ようやくビギナーからアマチュアになった気がします。

StoryboardでTable Viewのカスタムセルを作って、表示させるやり方。
メモ。

(1) プロジェクト新規作成して、UIViewController上にTable Viewを、その上にTable View Cellを追加。UITableViewControllerを使う場合はここは省略できます。

Pasted Graphic




(2) セル上に好きな部品を配置。後でこのセルを呼び出すために、Table View CellのIdentifierを設定します(下図ではhelloCell)。

Pasted Graphic 1

セルの中の各要素に後でアクセスするために、各
ViewにTagを設定。下図ではLabelに”1”のTagを設定してます。

Pasted Graphic 2

もう一個セルを追加してみる。セルの追加は、Table View Cellをドラッグ&ドロップ。2つ目のセルにもIdentifierを設定。部品を適当に配置。

Pasted Graphic 3





(3) Table Viewをソースコードに紐付け。Table ViewでCtrl押しながらうにょ〜と.h に登録。

Pasted Graphic 4




(4) 後はコードを書くだけ。

[ViewController.h]

#import

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{

}

@property (weak, nonatomic) IBOutlet UITableView *myTableView;
@end




[ViewController.m]


#import "ViewController.h"


@implementation ViewController
@synthesize myTableView;

- (
void)viewDidLoad
{
[
super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

[
myTableView setDataSource:self];
[
myTableView setDelegate:self];
}

- (
void)didReceiveMemoryWarning
{
[
super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}


#pragma mark - Table view data source

- (
NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1; //とりあえずセクションは1
}

- (
NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 2; //とりあえず2行だけ表示する
}

- (
UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

UITableViewCell *cell;

if(indexPath.row==0){ //0行目のセル
//カスタムセルを選ぶ
cell = [
myTableView dequeueReusableCellWithIdentifier:@"helloCell"];

//各要素にはタグでアクセスする
UILabel *idLabel = (UILabel*)[cell viewWithTag:1];
idLabel.
text = @"Bye";

}
else if(indexPath.row==1){//1行目のセル
cell = [
myTableView dequeueReusableCellWithIdentifier:@"switchCell"];
}

return cell;
}

@end




実行するとこんな感じ。
iOS Simulator Screen shot 2013.02.22 15.36.46

iPhone(iOS) + XMPP

iPhoneのXMPPに関する情報がJavaに比べて少ないので、メモ。色々ライブラリはあると思うが、RobbieHansonの XMPPFramework for OSX/iOSに関して。

(1) Xcodeへの設定

基本的には上記サイトのGettingStarted_iOSを見ながらやれば問題はない。しかしこっちの方が、スクリーンショットとか豊富で安心かも。ただし、情報が古いため、XMPPFramework-master/Authenticationも加えるのを忘れないように。
Build Phase->Link Binary with Libraries のframeworkの追加や、KissXMLを使うためのlibxml関係のリンクフラグなどの設定が少し面倒かな。。
自分の環境では、こんな感じ。
Pasted Graphic

Pasted Graphic 1

最後に.hファイル、XMPPFramework-master/Sample_XMPPFramework.hを、XMPPFramework.hっていう名前にして、自分が使うライブラリに応じて中身を書き換えてやってXcodeに置いとけば、#importが後々楽になる。

(2) とりあえず接続

サンプルコードを見ればわかりますが、念のためメモ。
XMPPStreamインスタンスを作るー>JIDの設定ー>Delegateの登録ー>コネクトー>コネクトできたらパスワードで認証(Delegateメソッド内で行う)
という感じで処理が進む。

例えばこんなコード。setupStreamを適当な場所で呼んでやり、ほっといたらすぐにxmppStreamDidConnectが呼ばれます。:

- (void)setupXMPPStream{
DDLogVerbose(@"%@: %@", [self class], THIS_METHOD);

xmppStream = [[XMPPStream alloc] init]; //XMPPStreamインスタンスを作る
xmppStream.myJID = [XMPPJID jidWithString:myJID]; //JIDの設定(hoge@hogehoge.comみたいなのがJID)

[
xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; //Delegateの登録

NSError *error = nil;

if (![xmppStream connect:&error]) //コネクト
{
DDLogError(@"%@: Error connecting: %@", [self class], error);
}

}

- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
NSError *error = nil;

if (![xmppStream authenticateWithPassword:_pass error:&error])
{
DDLogError(@"%@: Error authenticating: %@", [self class], error);
}

}



(3) XEP-0060 PubSubについて


RobbieHansonのXMPPFrameworkにももちろんPubSubのExtensionは入っている。が、JavaのSmackに比べて少しAPIが少なく感じるのと、日本語英語含めてほとんどサンプルやチュートリアルが見当たらないので、メモ。

XMPPStreamインスタンスを作った時みたいに、pubsub用のインスタンスも作る。

xmppPubSub = [[XMPPPubSub alloc] initWithServiceJID:[XMPPJID jidWithString:@"pubsub.hoge.com”]];
[
xmppPubSub activate:xmppStream];
[
xmppPubSub addDelegate:self delegateQueue:dispatch_get_main_queue()];//Delegateの登録


後は、XMPPPubSubのメソッドを見ながら色々と試してみると良い[xmppPubSub createNode/deleteNode/subscribeToNode/unsubscribeToNodeなど..]。ちなみにPubSubノード一覧は、 [xmppPubSub discoverItemsForNode:nil];でゲットできました。何かIQを送った場合、その結果は下記のDelegateメソッドでゲットできる。


- (void)xmppPubSub:(XMPPPubSub *)sender didReceiveResult:(XMPPIQ *)iq{

// ここに処理を書けばOK。とりあえずメッセージの中身を確認したい場合は、NSLog(@“%@“,[iq XMLString]); なんかで見ればよい。普通のXMLなので、
// DDXMLElement *element = [[DDXMLElement alloc] initWithXMLString:[iq XMLString] error:nil];
// NSArray* allNodes = [element nodesForXPath:…..
// こんな感じで書いて行けば、、XPathでXMLノードにアクセスできる。

}



しかしiOSプログラミングとObjective-Cは普段使わないとすぐ忘れちゃう(T^T)
毎回ほぼ0からのスタートだから、大変。「はじめてのiOS」みたいなチュートリアルを何回見て何回忘れたことか・・
Interface Builderじゃなくて、storyboardってやつになったのね。もっと積極的かつ継続的に触って、忘れないようにしたいです。

Geo-SELECT memo(MySQL)

緯度経度から範囲指定でSELECTするメモ。たぶんまた使うと思うので。

(準備)
適当なデータベースに、テーブルを作成:
create table testdb( name text not null, latlng geometry, primary key(name(128)));
とりあえずシンプルなテーブルを用意。ここではnameをプライマリーキーに、latlngという要素はgeometry型。

適当にデータを突っ込む:
insert into testdb(name,latlng) VALUES ('testname1’,GeomFromText('POINT(139.777 35.713)'));
insert into testdb(name,latlng) VALUES ('testname2’,GeomFromText('POINT(-79.945039 40.444663)'));

(ゲット)
SELECT name, Y(latlng) as lat, X(latlng) as lng from testdb where MBRContains(GeomFromText('LINESTRING(最大経度 最大経度, 最小経度 最小緯度)'),latlng);

これで最大緯度経度、最小緯度経度を対角とする四角形の範囲に存在するデータをとってくる。

最大緯度・経度は、こんな感じで求めた。

float minLat,maxLat,minLon,maxLon;
float lat = 中心の緯度の値;
float lon = 中心の経度の値;
float dist = 円でいう半径の値;

float earthLen = (float) ((float)6356752*Math.cos(lon/(180*Math.PI))*(2*Math.PI));
float meterPerSec=earthLen/(360*60*60);

minLat = lat - (dist/30.8184*0.00027778f);
maxLat = lat + (dist/30.8184*0.00027778f);
minLon = lon - (dist/meterPerSec*0.00027778f);
maxLon = lon + (dist/meterPerSec*0.00027778f);

このmin/maxLat, min/maxLonを上のSelect分の最大/最小緯度経度に当てはめたらオッケっぽい。

参考:
MySQLで指定した緯度経度から半径nメートル内検索っぽいのを実現するSQL
データベース内の緯度・経度を利用して半径500m以内を検索する方法