パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください -25ページ目

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

こんにちわ。ゆんぼうです。

今回は、iOSのAPIを使用して現在位置を取得します。

今回の開発環境は以下の通りです。
・OS X v10.9.3
・Xcode v5.1.1

位置情報を取得するクラス CLLocationManager を使用します。
インスタンスメソッド startUpdatingLocation で位置情報の取得を開始します。


self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];


取得の開始後、呼び出されるデリゲートメソッドは下記の通りです。

- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
取得に成功したときに呼び出される。

- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
取得に失敗したときに呼び出される。



- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
self.latitude = newLocation.coordinate.latitude;
self.longitude = newLocation.coordinate.longitude;

[self.locationManager stopUpdatingLocation];
}


取得に成功したときは、CLLocation オブジェクトから、
現在位置の緯度(latitude)及び、経度(longitude)を取得することができます。
また、インスタンスメソッド stopUpdatingLocation で取得の停止を行います。


位置情報の取得を行うアプリを作成する際に注意事項があります。
それは、アプリをApp Storeに登録時の審査のガイドラインに記載されています。

App Store Review Guidelines
https://developer.apple.com/appstore/resources/approval/guidelines.html

4. Location
4.1 Apps that do not notify and obtain user consent before collecting, transmitting, or using location data will be rejected

位置情報を収集する前に通知しない、またはユーザーの同意を得ないまま送信、
使用するアプリはリジェクト対象となります。

したがって、位置情報を取得する場合は、
下記のような同意ポップアップ、または通知ポップアップを表示しましょう。


UIAlertView *alert = [[UIAlertView alloc] init];
alert.delegate = self;
alert.message = @"現在位置を取得しますか?";
[alert addButtonWithTitle:@"いいえ"];
[alert addButtonWithTitle:@"はい"];
[alert show];


以上です。
こんにちわ。ゆんぼうです。

前回の続きで、今回はCoreDataを用いて、データベース検索を行います。

今回の開発環境は以下の通りです。
・OS X v10.9.3
・Xcode v5.1.1

前回作成したDAOクラス SampleEntityDAO に
名前と年齢で検索を行うインスタンスメソッドを追加します。


- (NSArray *)getSampleEntityItemList:(NSString *)name age:(NSNumber *)age
{
AppDelegate *appDeletage = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *managedObjectContext = [appDeletage managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];

NSEntityDescription *entityDes = [NSEntityDescription entityForName:@"SampleEntity" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityDes];

if(nil != name || nil != age){
NSMutableArray *predicateCommandArray = [[NSMutableArray alloc]init];

if(nil != name){
NSString *nameWord = [NSString stringWithFormat:@"*%@*",name];
NSPredicate *predicate = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"name"] rightExpression:[NSExpression expressionForConstantValue:nameWord] modifier:NSDirectPredicateModifier type:NSLikePredicateOperatorType options:0];
[predicateCommandArray addObject:predicate];
}

if(nil != age){
NSString *predicateCommand = [NSString stringWithFormat:@"(age = %@)",age];
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateCommand];
[predicateCommandArray addObject:predicate];
}

if(nil != predicateCommandArray){
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateCommandArray];
[fetchRequest setPredicate:predicate];
}
}

NSSortDescriptor *sortDes = [[NSSortDescriptor alloc]initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDes, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSError *error = nil;
NSArray *itemList = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if(nil != error){
NSLog(@"SampleEntityDAO#getSampleEntityItemList error %@, %@", error, [error userInfo]);
}
return itemList;
}


検索条件は、NSPredicateクラスを使用します。
複数ある場合は、NSPredicate オブジェクトを配列にして、
NSCompoundPredicate クラスを用いて条件を纏めます。

ここでは、名前と年齢の検索条件の NSPredicate オブジェクトを作成して、
andPredicateWithSubpredicates クラスメソッドを用いて、AND条件で纏めています。

まず、年齢の検索条件を見てみると
文字列の条件式 「age = %@」を predicateWithFormat クラスメソッドで
NSPredicate オブジェクトを作成します。

次に、名前の検索条件を見てみると、
下記のように文字列の条件式「name LIKE '*%@*'」で実装することもできますが、
ここでは実装しておりません。

NSString *predicateCommand = [NSString stringWithFormat:@"name LIKE '*%@*'",name];

なぜならば、悪意を持ったユーザーがいて、
この名前の値にSQL文を指定すると、そのSQL文が実行されてしまいます。
このSQL文を利用して、データベースを不正に操作する攻撃をSQL Injectionといいます。

SQL Injection を回避するため、
「name LIKE '*%@*'」のような文字列で条件式を作成するのではなく、
NSComparisonPredicate クラスを用いて、条件式を作成します。


この検索条件の呼び出し側を実装します。
1回目は、「お」を含む名前でデータベースを検索します。
2回目は、年齢が29でデータベースを検索します。
3回目は、「さ」を含む名前、かつ年齢が29でデータベースを検索します。



NSLog(@"---------------------------------------");
NSArray *item2List = [dao getSampleEntityItemList:@"お" age:nil];
for(SampleEntity *item in item2List) {
NSLog(@"name:%@, age:%@",item.name, item.age);
}
NSLog(@"---------------------------------------");
NSArray *item3List = [dao getSampleEntityItemList:nil age:[NSNumber numberWithInt:29]];
for(SampleEntity *item in item3List) {
NSLog(@"name:%@, age:%@",item.name, item.age);
}
NSLog(@"---------------------------------------");
NSArray *item4List = [dao getSampleEntityItemList:@"さ" age:[NSNumber numberWithInt:29]];
for(SampleEntity *item in item3List) {
NSLog(@"name:%@, age:%@",item.name, item.age);
}
NSLog(@"---------------------------------------");


実行すると下記の内容になります。

出力結果
---------------------------------------
name:しおぼう, age:40
---------------------------------------
name:あさぼう, age:29
---------------------------------------
name:あさぼう, age:29
---------------------------------------

以上です。
会員No.18です。

これからはコンテナ型仮想化技術だそうです。
http://www.docker.com/whatisdocker/

コンテナとはアプリケーションごとに隔離した空間のことで、
コンテナ型仮想化技術ではVMと違って複数のゲストOSを立ち上げるのではなく、1つのOSイメージ上で複数のコンテナを立ち上げることによって仮想化を実現するようです。

物理マシン1台に1つのOSの実行イメージで済むため、迅速かつ軽量に起動でき、メモリやCPUの利用効率が高いそうです。
皆様、おはようございます…(?)
紅焔、とでも名乗っておきましょうか。
わかる人はわかりますね? 運命浄化!

というわけで、しょうもないことかもしれませんがjspで開発をしてる時に詰まった事があったので備忘録も兼ねて書き記したいと思います。

EclipseでJSPアプリケーションを開発していて、XMLのパースをしたくてDOM4Jのライブラリーを組み込もうと思い、プロジェクト配下にフォルダを作ってコピーし、ビルドパスを通して
さぁ、実行…!

java.lang.NoClassDefFoundError

なんでやー!(・∀・#)
ビルドパスは通ってるのにー!
ソース上でもエラーは出ないのにー!

これはJSPのアプリケーションであり、単なるjavaのアプリケーションではないのです。
プロジェクト配下に置いて、ビルドパスを通す…。
このjarが見えているのはそう、eclipseだけなのです。

JSPアプリケーションからは見えていないのです。

解決方法は、
WebContentのWEB-INF/libにjarを置く
事でした。

ここに置くことで、外部jarはJSPアプリケーションから見えるようになり、晴れて使用できる訳で御座います。

単純なことでしたが、解決に時間がかかってしまったので、同じ事で悩む人が居なくなることを願って、締めとさせて頂きます。

それでは皆様、おやすみなさいませ、おやすみなさいませ…(謎)
【議題】
mobile safariにおいて、ブラウザの戻るボタンを無効化したい(対象OS:iOS7)

【調査結果】
真の意味において無効化(ボタンが押せないor押しても無反応)は実現不可能

【対応策】
擬似的に無効化させる(戻るボタン押下にて画面遷移後、元の画面に戻る)


[ポイント①] 以下の3つの仕様を利用する
 ※ブラウザの戻るボタンを押下したタイミングで呼ばれる、
  『押下時点でactiveな画面のwindow.onunloadファンクション』
 ※一つ前のページへ戻るJavaScript関数『history.back()』
  (= 一般的なブラウザの戻るボタンを押したときと同じ動作をします)
 ※一つ先のページへ遷移するJavaScript関数『history.forward()』
  (= 一般的なブラウザの進むボタンを押したときと同じ動作をします)

[ポイント②] ブラウザの戻るボタン押下時のMobile Safariの仕様を理解する
 ※onloadイベント → 実行されない。
 ※onpageshowイベント → 実行される。
 


上記のポイントを踏まえて、以下のように実装を行いました。


//---------------------------------------------//
// ブラウザの戻るボタンを無効化したい画面.html //
//---------------------------------------------//
window.onunload = function() {
history.back(); // 一つ前のページへ戻る …①
}


//-----------------------------------------------------//
// ブラウザの戻るボタンにて表示される一つ前の画面.html //
//-----------------------------------------------------//
window.onload = function() {
…ページが読み込まれた時に行う処理を記述(通常表示時の処理を記述する)
}

window.onpageshow = function() {
history.forward(); // 一つ先のページへ遷移する
// …①により当ファンクションが呼び出されるため、ここで元の画面へ遷移する処理を行う
}


以上の方法により、ブラウザの戻るボタンを無効化(と同様の動作を実現)致しました。