Objective-c覚書

Objective-cで調べた事をメモ
***
**システム日付と時間の取得**
参考サイト：http://www.srcw.net/wiki/index.php?Objective-C%2F%C6%FC%C9%D5%A4%C8%BB%FE%B9%EF
　　　　　　http://iritec.jp/web_service/5078/

　**NSDateを文字列に変換する**
　NSDateFormatterを使って書式指定する方法

```objective-c:sample.m
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:@"YYYY/MM/dd HH:mm:ss"];
NSDate* date = [NSDate date];
NSString* dateStr = [formatter stringFromDate:date];
```

上記コードだと「[[[NSDateFormatter alloc] init] autorelease]」の部分が使用出来ないみたい。なので、下記に変更する。

```objc:sample.m
NSDate *nowdate = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
NSString *datamoji = [formatter stringFromDate:nowdate];
```

取得できることが確認できました。

***
**テキスト入力フィールドでのイベント**
参考サイト：http://start-xcode.blog.so-net.ne.jp/2011-07-07

　**・UITextFieldアクションメニュー**
 　　Did End On Exit：テキスト編集の終わりにEnter（Return）がタップされた時
 　　Editing Changed：テキストフィールドで文字が変更されたその時
 　　Editing Did Begin：テキスト入力が始まった最初の時
 　　Editing Did End：テキスト入力が終わった時
 　　Touch Cancel：テキスト入力動作がキャンセルされた時（アプリが切り替わりテキスト入力が中断してしまった時）
 　　Touch Down：パーツ内に触れた時
 　　Touch Down Repeat：パーツ内で２回以上触れた時（ダブルタップ又はそれ以上の回数）
 　　Touch Drag Enter：パーツ内から外へドラックして再び戻ってきた時
 　　Touch Drag Exit：パーツ内から外へドラックされた時
 　　Touch Drag Inside：パーツ内でドラックが行なわれた時
 　　Touch Drag Outside：パーツ内から外へドラックが行なわれた時
 　　Touch Up Inside：タップされた時
 　　Touch Up Outside：タップ動作でパーツの外で離された時
 　　Value Changed：使用者又はプログラム経由にかかわらずテキストが変更された時

***

**UITextView の編集検知**
参考サイト：http://kawairi.jp/weblog/vita/201311189607

UITextView が編集された事を検知し、処理を行う場合にはUITextViewDelegate のtextViewDidChange: メソッドを利用する。

***

**UITableViewCell上に配置したButtonのタップを感知する方法**
参考サイト：http://qiita.com/tomochang/items/8770c1963afd8157e56b

```objc:sample.m
//---------------------------------
// セルの内容表示
//---------------------------------
- (UITableViewCell*)tableView:(UITableView *)tableView
        cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
    static NSString* CellIdentifier = @"Cell";
    myTVCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [[myTVCell alloc] initWithStyle:UITableViewCellStyleDefault
                                        reuseIdentifier:@"myTVCell"];
    }
 
    // タッチイベントを追加    
    [cell.myButton addTarget:self action:@selector(onMyButtonTouch:event:)
                                        forControlEvents:UIControlEventTouchUpInside];
 
     
    return(cell);
}
 
 
//---------------------------------
// ボタンが押された時の処理を記述
//---------------------------------
- (void)onMyButtonTouch: (UIButton *)sender
                  event:(UIEvent *)event
{
    // 押されたボタンのセルのインデックスを取得
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint point = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
 
    // ログを出力    
    NSLog(@"row : %d", indexPath.row);
}
```

インデックスを取得する事ができました。

***
**配列から特定の要素を削除する方法**
参考サイト：http://www.objectivec-iphone.com/foundation/NSArray/removeObject.html

![image](https://qiita-image-store.s3.amazonaws.com/0/67341/98059b50-935a-0078-fc73-442069fa7c3f.png)

```objc:sample.m
// 配列から@"Spike"を削除する
NSMutableArray *ary1 = [NSMutableArray arrayWithObjects:
                 @"Snoopy", @"Spike", @"Olaf", nil];
 
[ary1 removeObject:@"Spike"];
NSLog(@"%@", ary1);
 
 
// インデックスを指定して配列から要素を削除する
NSMutableArray *ary2 = [NSMutableArray arrayWithObjects:
                 @"Snoopy", @"Spike", @"Olaf", nil];
 
[ary2 removeObjectAtIndex:1];
NSLog(@"%@", ary2);
 
 
// 範囲を指定して配列から要素を削除する
NSMutableArray *ary3 = [NSMutableArray arrayWithObjects:
                 @"Snoopy", @"Spike", @"Olaf", nil];
 
[ary3 removeObjectsInRange:NSMakeRange(0, 1)];
NSLog(@"%@", ary3);
 
 
// 配列の要素をすべて削除する
NSMutableArray *ary4 = [NSMutableArray arrayWithObjects:
                 @"Snoopy", @"Spike", @"Olaf", nil];
 
[ary4 removeAllObjects];
NSLog(@"%@", ary4);
```

狙い通り、削除できました！！

***
**空文字列のチェック**
参考サイト：http://qiita.com/YusukeHosonuma/items/3103ca5353fd585b08bd

既存プログラムの中で、以下のコードが使用されていたので
合わせることにした。

```objc:sample.m
// 明示的なnilおよび長さチェック
if (someString == nil || [someString length] == 0) 
```

***
**差分チェックをおこなう方法**
参考サイト：http://kojisatoapp.blogspot.jp/2014/04/xcodedifffilemerge.html

***
**Exitで戻る処理を定義する**
参考サイト：http://dev.classmethod.jp/smartphone/iphone/ios_unwind-segue/

***
**設定できる色**
参考サイト：http://www.sirochro.com/note/objc-uicolor-rgb/

***
**ボタンの表示がiOS7.0仕様になってしまう・・・**
参考サイト：：http://h2ham.net/ios-simulator-tips

iOSシミュレータにiOS6.0版を追加してみたら、表示されるようになった。

***
**C言語の文字const char *とObjectiveCの文字列NSStringの変換Add Star**
参考サイト：http://d.hatena.ne.jp/eidolon/20121125

***
**objective-C文字列の比較は==ではダメ**
参考サイト：http://d.hatena.ne.jp/kemworld/20101126/1290757554

***
**複数複数のUIAlertViewを使う時のclickedButtonAtIndex**
参考サイト：http://qiita.com/corona6@github/items/d740646f299630f1ab0d

***
**小文字(英字)を大文字(英字)に変換する方法**
参考サイト：http://www.objectivec-iphone.com/foundation/NSString/uppercaseString.html

```objc
NSString *str = @"snoopy";
 
// 大文字に変換
NSString *upperStr = [str uppercaseString];
NSLog(@"%@", upperStr);
 
// 小文字に変換
NSString *lowerStr = [upperStr lowercaseString];
NSLog(@"%@", lowerStr);
```

***
**テーブルのセクションヘッダーにボタンを追加する**
参考サイト：http://kiririmode.hatenablog.jp/entry/20110828/p1

***
**ラベルをコード上で追加した場合の背景色の設定**
参考サイト：http://iphone-app-program.com/objective-c/uicolor/colorbase/

　コード上で、テーブルビューのセクションヘッダーにラベルを追加したけれど
　背景色がデフォルトで白だった…。
　なので、何とかテーブルビューの背景と合わせようと色を設定したけれど微妙に合わず…
　（テーブルビューの背景色の設定が「Default」だったので、色を抽出してRGBの設定をしたｋれどうまくいかなかった)

　結局、「clearColor(透明)」でうまくいきました。(やれやれ^^;)

***
**配列をコピー＆削除する方法**
参考サイト：http://www.objectivec-iphone.com/foundation/NSArray/arrayWithArray.html

　編集をする前に配列をコピーしておいて、データが確定したら編集した仮の配列を本番用配列に戻す方法を検討していた。

```objective-c:sample.m
// コピー元の設定
NSArray *src = [NSArray arrayWithObjects:@"Snoopy", @"Spike", @"Olaf", nil];
// コピー
NSArray *dst = [NSArray arrayWithArray:src];

// 配列の要素をすべて削除する
NSMutableArray *ary4 = [NSMutableArray arrayWithObjects:@"Snoopy", @"Spike", @"Olaf", nil];
 
[ary4 removeAllObjects];
```

***
**文字列NSStringとCharの変換方法**
参考サイト：http://www29.atwiki.jp/sonicbrain/pages/17.html

・NSString*->char*への変換

```objc:sample.m
NSString* str = "AAA";
char* cp = [str UTF8String];
```

・char*->NSString*への変換

```objc:sample.m
char* cp = "AAA";
NSString* str = [NSString stringWithCString: cp encoding:NSUTF8StringEncoding];
```

***
**objective-cからのDB接続**
objective-cからのDB接続

質問
iPhoneアプリを開発しています。

objective-cからデータベースに接続し、

データを取得・更新を行いたいのですが、

可能なのでしょうjか？

できるのであれば、どのようにすればできるか、教えてください。

データベースはサーバ上にFilemakerで作成されています。

objective-cからは無理であれば、サーバにPHPファイルを書いておいて、

PHPにアクセスして、データベースへのアクセスでもOKです。

objective-cからのPHP実行に関しても、ご存じの方、教えてください。

宜しくお願いします。。

回答
こんにちは。

たとえば、MySQLならPHPのWebAPIが用意されているので、iOS(Objective-C)からMySQLのDBを利用する事例は捜せばいくらでもあります。
MySQLにはC言語用のlibMySQLライブラリもありますが、WebAPIはHTTPなので、このほうが作りやすいと思います。

Filemaker社がPHP用のWebAPIを公開しているなら、MySQLの事例を参考にして開発されるといいです。

PHP用のWebAPIがあるとして、

サーバ側(Filemaker, ApacheとPHP)には、DB接続用、情報登録、更新、取得、一覧取得、削除処理のPHPスクリプトがたぶん必要でしょう。

iOS側では、HTTP非同期通信処理が必要なので、NSURL, NSURLRequest, NSURLConnectionクラスを組み合わせて開発することになります。
主な処理はそれらのクラスのデリゲートの中に記述することになると思います。

iOS側からサーバへの情報送信には、HTTPのPOSTまたはGETメソッドを利用することになります。

GETメソッドの場合はURLにURLパラメータを記述して、情報をiOSからサーバーに渡すことになります。
こんな感じで( http://サーバー名/phpスクリプト名?パラメータ1=値?パラメータ2=値....)

POSTメソッドを使うならNSMutableURLRequestクラスで、URLに含めずに情報を渡すことになります。

サーバからの受信は、データを受信するごとにNSURLConnectionのデリゲートが呼ばれるので、その中で処理することになります。

受信データは、サイズが小さければバッファにすべて保存できますし、大きければ、逐一ファイルに書き込む処理が必要です。

受信データの形式は、FTPのようにビットストリームかXMLやJSON、独自フォーマットなど考えられますが、それぞれに応じたフレームワークやパースの仕組みが必要になります。

***
**iPhoneからMySQLへ接続アプリ**

iPhoneからMySQLへの接続 アプリAdd Star

iPhoneアプリ開発, PHP

現在作成してるアプリでデータベースへの接続をする必要性があった。

使用するデータベースはMySQL

今回使用するデータベースへの接続方法は、

別のサーバを仲介してデータをそのサーバに処理してもらう方法です。iPhoneからやるのはデータの送受信のみ。

中間サーバではPHPを使用しMySQLへ接続します。

全体の流れ

    iPhoneでGETメソッドを作成する。
    データの送信をする
    phpデータを受け取り,mysqlにつなぎDB操作をする
    返ってきたデータをXMLParserでパースする


データの送受信

    NSURLConnection,NSRequestを使用し送信のみを行う。
    NSXMLParserを使用し送受信を行う。
    NSURLConnection,NSRequestを行った後、NSXMLParserで解析を行う

主にこの方法があると思います。

送信だけなら1番、データが少ないのであれば2番にurlを渡す。データが大きくなる場合は3番でデータを渡す。でいいのではないでしょうか。

今回はgetリクエストを送信しXMLParserで解析を行い、tableViewに一つずつ表示していきます。

ListViewController.h

#import <UIKit/UIKit.h>

@class XMLParser;

@interface ListViewController : UITableViewController{

    XMLParser *xmlParser;

}

@property (nonatomic, retain) XMLParser *xmlParser;

@end

ListViewController.m


#import "ListViewController.h"

#import "XMLParser.h"

@interface ListViewController ()

@end

@implementation ListViewController

@synthesize xmlParser;

//メモリの解放
- (void)dealloc{
    [xmlParser release];
    [super dealloc];
}


//ビューが表示される前に実行
- (void) viewWillAppear:(BOOL)animated{
    
    //urlの作成
    NSString *url=@"http://xxx.com/xxx.php?table_name=ranking&query_type=select";
    
    //urlへGetリクエストを送信
    xmlParser=[[XMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
    
    //デリゲートをセット
    [xmlParser setDelegate:xmlParser];
    
    //パース開始
    [xmlParser parse];
    
    //テーブルビューを再描画
    [self.tableView reloadData];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //xmlParserで取得した内容の数
    return [xmlParser.xmlElements count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //tableViewCellの作成
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil){
        cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
        cell.selectionStyle=UITableViewCellSelectionStyleNone;
    }
    
    //テーブルビューに取得したxmlの内容を入れていく
    cell.textLabel.text=[[xmlParser.xmlElements objectAtIndex:indexPath.row ]objectAtIndex:1];

    //セルを返す
    return cell;
}

//テーブルのセルが選択された場合の処理
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 
}

@end

XMLParser.h

#import <Foundation/Foundation.h>

@interface XMLParser : NSXMLParser <NSXMLParserDelegate>{

    NSMutableArray *xmlElements;//受信した情報が配列で入る
}

@property (nonatomic, retain) NSMutableArray *xmlElements;

- (NSArray *) parse:(NSData *) xmlData;

@end

XMLParser.m

#import "XMLParser.h"

@implementation XMLParser

@synthesize xmlElements;

//Document開始
- (void)parserDidStartDocument:(NSXMLParser *)parser{
    //配列を初期化
    self.xmlElements=[[NSMutableArray alloc]init];
    
}

//開始エレメント
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    
    //エレメント開始
    if(qName){
        elementName=qName;
    }
    
    //情報をxmlElementsに格納
    if([elementName isEqualToString:@"figure"] || [elementName isEqualToString:@"ranking"]){
        NSArray *tempArray=[[NSArray alloc]initWithObjects:
                            [attributeDict objectForKey:@"id"],
                            [attributeDict objectForKey:@"name"],
                            nil];
        [xmlElements addObject:tempArray];
    }
    
    if([elementName isEqualToString:@"answer"]){
        NSArray *tempArray=[[NSArray alloc]initWithObjects:
                            [attributeDict objectForKey:@"id"],
                            [attributeDict objectForKey:@"column1"],
                            [attributeDict objectForKey:@"column2"],
                            [attributeDict objectForKey:@"column3"],
                            [attributeDict objectForKey:@"writer"],
                            nil];
        [xmlElements addObject:tempArray];
    }
}

//終了エレメント
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
}

//要素中の文字列発見
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
}


- (NSArray *)parse:(NSData *)xmlData{
    
    NSXMLParser *parser=[[NSXMLParser alloc]initWithData:xmlData];
    [parser setDelegate:self];
    [parser parse];
    [parser release];
    
    return self.xmlElements;
  
}

- (void)dealloc{
    [xmlElements release];
    [super dealloc];
}
@end

xxx.php

<?php
include_once "DatabaseClass.php";

if($_GET["table"])
{
	//instance create
	$database=new Database();
	//テーブル名の取得
	$table=$_GET["table"];
	//クエリタイプの取得
	$query_type=$_GET["query_type"];

if($table=="figure"||$table=="ranking"){
	switch($query_type){
	//<db_table>
	//		<$table id=$id name=$name />
	//		<$table id=$id name=$name />
	//</db_table>
	case "select":
		$category=$_GET["category"];
		$select="select id, name from $table where category=$category";
		$row=array();
		$row=$database->array_select($select); 
		if($row!=null){
			$xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
			$xml.="<db_table>\n";
			foreach($row as $value)
			{
				$id=$value["id"];
				$name=$value["name"];
				$xml.="<$table id=\"$id\" name=\"$name\" />\n";
			}//foreach
			$xml.="</db_table>\n";
			echo $xml;
		}//if($row!=null)
		break;
	}//switch($query_type)
}//if($table=="figure"||$table=="ranking")
	$database->close();
}//if($_GET["table"])

?>

DatabaseClass.php

<?php

//mb_language("uni");
//mb_internal_encoding("utf-8");
//mb_http_input("auto");
//mb_http_output("utf-8");

class Database{

	var $dbServer;
	var $dbName;
	var $dbUser;
	var $dbPass;
	var $link;
	var $db;

	//constract
	function Database()
	{
		//ここを入力
		$this->dbServer="";
		$this->dbName="";
		$this->dbUser="";
		$this->dbPass="";
		
		//connect mysql
		$this->link=mysql_connect($this->dbServer,$this->dbUser,$this->dbPass)or die(exit);
		
		//database select
		$this->db=mysql_select_db($this->dbName,$this->link);
	}
	
	public function close()
	{

		return mysql_close($this->link);

	}
	
	public function select($query)
	{
		
		$result=mysql_query($query);
		$row=array();
		$row=mysql_fetch_assoc($result);
		return $row;
	}
	public function array_select($query)
	{
		$row=array();
		$i=0;
		$element=array();
		$result=mysql_query($query);
		while($element=mysql_fetch_assoc($result)){
			$row[$i]=$element;
			$i++;
		}
		return $row;
	}	
	public function query($query)
	{
	
		return mysql_query($query);

	}
}
?>