アプリバージョンの取得を行う方法(強制アップデート)【Objective-C】

■はじめに

アプリでよくある、最新版のアプリじゃないと、アップデートしてね〜

というようなダイアログを出す場合があります。

これは、最新アプリがあるのに、古いバージョンのアプリを利用されないようにするためには、非常にいい方法です。

ここでは、AppStoreのアプリのバージョンの取得方法を記載します。

■手順

URLのリクエストで、バージョン情報を取得するのですが、URLにはそのアプリのIDが必要になります。

これは、iTunes Connectで確認してください。(アプリが既にリリースされている必要があります。)

以下のURLの「[Apple ID]」の部分をそのIDに書き換えてください。

https://itunes.apple.com/lookup?id=[Apple ID]

以下がリクエストを行い、バージョン情報をコンソールに出力する処理です。

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://itunes.apple.com/lookup?id=[Apple ID]"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
[[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error || [(NSHTTPURLResponse *)response statusCode] != 200) {
return;
}
NSLog(@"=====成功======");
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", dic[@"results"][0][@"version"]);
}] resume];

NSUserdefaultsにNSMutablearrayを格納する/読み出す【Objective-C】

◾️はじめに

「NSUserDefaults」を使用して、データの保存などを行う際に、リスト形式のデータをそのまま
使用したい場合がある。
ここでは、「NSUserDefaults」に「NSMutableArray」を格納、取得を行う方法を記載する。

◾️NSUserDefaultsにNSMutableArrayを格納する

「NSUserDefaults」に「NSMutableArray」を格納するには、そのままでは格納ができない。
その為、一旦「NSData」に変換してから格納する。

具体的には、以下の様に設定する。
(以下では、「NSMutableArray」に値を設定していないが、設定しても同様です。)

// NSUserDefaultsのインスタンスを生成する
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// NSUserDefaultsに格納するNSMutableArrayのインスタンスを生成する
NSMutableArray *array = [[NSMutableArray alloc] init];
// NSMutableArrayをNSData型に変換する
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
// NSUserDefaultsに値を設定する
[ud setObject:data forKey:@"TargetKey"];
// 設定を反映する
[ud synchronize];

◾️ NSUserDefaultsからNSMutableArrayを取得する

「NSUserDefaultsにNSMutableArrayを格納する」で記載した通り、「NSMutableArray」を
「NSUserDefaults」に格納するために、「NSData」型に変換した。
そのため、取得する際には、「NSData」型から「NSMutableArray」に変換する必要がある。

具体的には、以下の様に取得する。

// NSUserDefaultsのインスタンスを生成する
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// NSUserDefaultsからNSData型の値を取得する
NSData *data = [ud objectForKey:@"TargetKey"];
// NSData型からNSMutableArray型へ変換する
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data];

SQLiteの使用方法【Objective-C】

◾️はじめに

データを永続的に保存する方法で、数々の方法があります。
以下に一例を挙げます。
・NSUserDefaults
・CoreData
SQLite
・Realm

ここでは、「SQLite」に関して記載します。
SQL文に関しては、簡単なサンプルや記載方法は記載するが細かい部分は別途調査する事。

◾️SQLiteとは

SQLiteとは、数あるSQLの中の一つです。
※ちなみに、SQLとはDB(データベース)を定義したり操作したりするプログラミング言語です。

SQLiteの特徴として、他のSQLMySQL,Oracleなど)と違い、DBをファイル形式で保持する事ができます。
※他のSQLMySQL,Oracleなど)のほとんどは、サーバー上にDBを保持します。

上記の特徴があるため、ローカルにDBファイルを保存しておく事で、サーバーへ接続する必要がなくなるメリットがあります。

◾️SQLiteのインポート

SwiftでSQLiteを使用する為に、便利なライブラリが色々とありますが
ライブラリを使用したくない場合もありますよね。(現場の方針など。。。)

ここでは、ライブラリを使用しないSQLiteの操作を記載します。

まずは、SQLiteを操作する為に以下をインポートします。
SQLiteの操作をするクラスでは必ずインポートしてください。

ソースコードを記載する前に、「Linked Frameworks and Libraries」に「libsqlite3.0.tbd」を追加する必要がある。

@import SQLite3;

◾️DBファイルの定義

SQLiteとは」で説明した通り、SQLiteはDBをファイル形式で保持しています。
そのため、まずはDBファイルを生成する必要があります。

まずは、フィールド変数に、以下を定義してください。
※都度定義するのが手間なので、まとめて。

// SQLiteのファイル名
NSString *dataFileName;
// SQLiteのファイルまでのフルパス
NSString *dataFileFullPath;
// 開いているSQLiteファイルのインスタンス
sqlite3 *sqlax;

上記を定義したら、SQLiteの物理ファイルを生成します。
以下のメソッドを定義して、呼び出してください。

/**
* SQLiteの物理ファイルの作成
*/
-(void)preparationOfPhysicalDiles {
// 1.【物理ファイルを準備します】
dataFileName = @"unkolist.sqlite3";
// 使用可能なファイルパスを全て取得する
NSArray *availablePats = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 最初のものを使用する
NSString *dir = [availablePats objectAtIndex:0];
// ファイルマネージャを召還する
NSFileManager *myFM = [NSFileManager defaultManager];
// 物理ファイルって既にありますか?
dataFileFullPath = [dir stringByAppendingPathComponent:dataFileName];
BOOL fileExists = [myFM fileExistsAtPath:dataFileFullPath];
// 無い場合はつくる
if (! fileExists) {
BOOL isSuccessfullyCreated = [myFM createFileAtPath:dataFileFullPath contents:nil attributes:nil];
if (! isSuccessfullyCreated) {
NSLog(@"新規ファイル作成に失敗しました=>%@", dataFileFullPath);
}
}
}

ここまでの下準備ができたら、以下のメソッドを実行し、SQLiteを開きます。
※テーブル作成などを行う前に、一番最初に実行する必要があります。

/**
* SQLiteを開くメソッド(※SQLの実行前には呼んでおく必要がある。)
*/
-(void)openSQLite {
BOOL isSuccessfullyOpened = sqlite3_open([dataFileFullPath UTF8String], &sqlax);
if (isSuccessfullyOpened != SQLITE_OK) {
NSLog(@"sqlite開けませんでした!=> %s", sqlite3_errmsg(sqlax));
}
}

これで、SQLiteを開く事ができたので、以降でDBの操作をします。

◾️Table作成(CREATE TABLE)

ここでは、テーブルの作成方法を記載します。

以下のメソッドを実行する事で、Tableの作成が可能です。
※以下のメソッドに記載しているSQL文は各自書き換えてください。

【テーブル作成のSQLの基本の記載方法】
CREATE TABLE [テーブル名] ([カラム名] [データ型], [カラム名] [データ型] ・・・)

/**
* テーブル作成処理
*/
-(void)createTable {
sqlite3_stmt *statement;
// CREATE TABLE文 (「IF NOT EXISTS」を書くことで、既に作成されている場合には処理しない)
NSString *query = @"CREATE TABLE IF NOT EXISTS sampleTable (name TEXT)";
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}

◾️カラムの登録(INSERT)

ここでは、カラムの登録方法を記載します。

以下のメソッドを実行する事で、カラムの登録が可能です。
※以下のメソッドに記載しているSQL文は各自書き換えてください。

【カラムの登録のSQLの基本の記載方法】
INSERT INTO [テーブル名] ([カラム名], [カラム名]・・・) VALUES ([データ], [データ]・・・)

/**
* データの追加処理
*/
-(void)insertData: (NSString*) name {
sqlite3_stmt *statement;
// INSERT
NSString *query = [NSString stringWithFormat:@"INSERT INTO sampleTable (name) VALUES (\"%@\")", name];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}

◾️データの取得(SELECT)

ここでは、データの取得方法を記載します。

以下のメソッドを実行する事で、データの取得が可能です。
※以下のメソッドに記載しているSQL文は各自書き換えてください。
※取得したレコードのループ処理は各自書き換えてください。

【データの取得のSQLの基本の記載方法】
SELECT * FROM [テーブル名]

/**
* データの検索処理
*/
-(void)selectData {
sqlite3_stmt *statement;
NSString *query = @"SELECT name FROM sampleTable";
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
while (sqlite3_step(statement) == SQLITE_ROW) {
char *ownerNameChars = (char *) sqlite3_column_text(statement,0);
NSLog(@"Found : %s", ownerNameChars);
}
sqlite3_finalize(statement);
}

◾️データの更新(UPDATE)

ここでは、データの更新方法を記載します。

以下のメソッドを実行する事で、データの更新が可能です。
※以下のメソッドに記載しているSQL文は各自書き換えてください。

【データの更新のSQLの基本の記載方法】
UPDATE [テーブル名] SET [カラム名] = [データ] WHERE [カラム名] = [データ]

/**
* データの更新処理
*/
-(void)updateData {
sqlite3_stmt *statement;
// UPDATE
NSString *query = [NSString stringWithFormat:@"UPDATE sampleTable SET name = \"KONBANWA\" WHERE name = \"HELLO\""];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}

◾️データの削除(DELETE)

ここでは、データの削除方法を記載します。

以下のメソッドを実行する事で、データの削除が可能です。
※以下のメソッドに記載しているSQL文は各自書き換えてください。

【データの削除のSQLの基本の記載方法】
DELETE FROM [テーブル名] WHERE [カラム名] = [データ]

/**
* データの削除処理
*/
-(void)deleteData {
sqlite3_stmt *statement;
// DELETE
NSString *query = [NSString stringWithFormat:@"DELETE FROM sampleTable WHERE name = \"HELLOHELLO\""];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}

◾️SQLiteを閉じる

以下のメソッドを実行する事で、SQLiteを閉じる事ができます。
SQLの処理が終わって、不要になれば閉じるようにしましょう。

/**
* SQLiteを閉じるメソッド(※SQLの実行後に呼ぶ必要がある。)
*/
-(void)closeSQLite {
// SQLiteを閉じる
sqlite3_close(sqlax);
}

◾️さいごに

色々と、書きましたが、私が動作確認で実行したソースを以下に記載しておきます。

#import "SQLiteViewController.h"
@import SQLite3;
@interface SQLiteViewController () {
// SQLiteのファイル名
NSString *dataFileName;
// SQLiteのファイルまでのフルパス
NSString *dataFileFullPath;
// 開いているSQLiteファイルのインスタンス
sqlite3 *sqlax;
}
@end
@implementation SQLiteViewController
- (void)viewDidLoad {
[super viewDidLoad];
// SQLiteの物理ファイルの生成
[self preparationOfPhysicalDiles];
// SQLiteを開く
[self openSQLite];
// テストでいくつかのSQLを実行する
[self test];
// SQLiteを閉じる
[self closeSQLite];
}
/**
* テストで適当なSQLを実行する
*/
-(void)test {
// CREATE TABLE
[self createTable];
// INSERT
[self insertData:@"HELLO"];
[self insertData:@"HELLOHELLO"];
[self insertData:@"HELLOHELLOHELLO"];
// UPDATE
[self updateData];
// DELETE
[self deleteData];
// SELECT
[self selectData];
}
/**
* SQLiteの物理ファイルの作成
*/
-(void)preparationOfPhysicalDiles {
// 1.【物理ファイルを準備します】
dataFileName = @"unkolist.sqlite3";
// 使用可能なファイルパスを全て取得する
NSArray *availablePats = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 最初のものを使用する
NSString *dir = [availablePats objectAtIndex:0];
// ファイルマネージャを召還する
NSFileManager *myFM = [NSFileManager defaultManager];
// 物理ファイルって既にありますか?
dataFileFullPath = [dir stringByAppendingPathComponent:dataFileName];
BOOL fileExists = [myFM fileExistsAtPath:dataFileFullPath];
// 無い場合はつくる
if (! fileExists) {
BOOL isSuccessfullyCreated = [myFM createFileAtPath:dataFileFullPath contents:nil attributes:nil];
if (! isSuccessfullyCreated) {
NSLog(@"新規ファイル作成に失敗しました=>%@", dataFileFullPath);
}
}
}
/**
* SQLiteを開くメソッド(※SQLの実行前には呼んでおく必要がある。)
*/
-(void)openSQLite {
BOOL isSuccessfullyOpened = sqlite3_open([dataFileFullPath UTF8String], &sqlax);
if (isSuccessfullyOpened != SQLITE_OK) {
NSLog(@"sqlite開けませんでした!=> %s", sqlite3_errmsg(sqlax));
}
}
/**
* SQLiteを閉じるメソッド(※SQLの実行後に呼ぶ必要がある。)
*/
-(void)closeSQLite {
// SQLiteを閉じる
sqlite3_close(sqlax);
}
/**
* テーブル作成処理
*/
-(void)createTable {
sqlite3_stmt *statement;
// CREATE TABLE文 (「IF NOT EXISTS」を書くことで、既に作成されている場合には処理しない)
NSString *query = @"CREATE TABLE IF NOT EXISTS sampleTable (name TEXT)";
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}
/**
* データの追加処理
*/
-(void)insertData: (NSString*) name {
sqlite3_stmt *statement;
// INSERT
NSString *query = [NSString stringWithFormat:@"INSERT INTO sampleTable (name) VALUES (\"%@\")", name];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}
/**
* データの更新処理
*/
-(void)updateData {
sqlite3_stmt *statement;
// UPDATE
NSString *query = [NSString stringWithFormat:@"UPDATE sampleTable SET name = \"KONBANWA\" WHERE name = \"HELLO\""];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}
/**
* データの削除処理
*/
-(void)deleteData {
sqlite3_stmt *statement;
// DELETE
NSString *query = [NSString stringWithFormat:@"DELETE FROM sampleTable WHERE name = \"HELLOHELLO\""];
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
sqlite3_step(statement);
sqlite3_finalize(statement);
}
/**
* データの検索処理
*/
-(void)selectData {
sqlite3_stmt *statement;
NSString *query = @"SELECT name FROM sampleTable";
sqlite3_prepare_v2(sqlax, [query UTF8String], -1, &statement, nil);
while (sqlite3_step(statement) == SQLITE_ROW) {
char *ownerNameChars = (char *) sqlite3_column_text(statement,0);
NSLog(@"Found : %s", ownerNameChars);
}
sqlite3_finalize(statement);
}
@end

UITableViewセルの選択を解除する【Objective-C】

◾️はじめに

UITableViewは活用していますか?
アプリを作る上で、UITableViewは必須と言えるほど利用頻度が高いです。
(個人的意見ですよ!!)

そのUITableViewにも欠点があります。
そう、UITableViewのCellをタップした後、選択状態が解除されないのです!!
灰色っぽいままになっちゃいます。。。

UITableViewの選択状態を解除するためには、実装が必要なのですよ。
これには、正直ビックリしましたが、仕方ない!と割り切りましょう。

ここでは、UITableViewの選択状態を解除する方法を記載します。
(UITableViewは表示できている前提で進めます。)

◾️UITableViewセルの選択を解除する

UITableViewの選択状態を解除するには、UITableViewのDelegateの「didSelectRowAtIndexpath」メソッドに
以下を記載する事で、解除されます。
※以下の処理が通る事で解除されるので、一定時間後に解除したい場合などは、遅延処理も行いましょう!

[self.tableView deselectRowAtIndexPath:indexPath animated:YES];

NSUserDefaultsの基礎【Objective-C】

◾️はじめに

アプリを作成していると、データを保存しておきたい時が多々あります。
(一例を挙げると、「設定」の値など)

そのような場合に、色々とデータを保存する方法はありますが、今回は「NSUserDefaults」に関して記載します。
ちなみに、NSUserDefaultsはアプリの保存ディレクトリに「plist」形式のファイルとして保持されます。

◾️データの保存、更新

ここでは、NSUserDefaultsへのデータの保存方法を記載します。
データの保存は、key,value形式で保存されます。

既に対象のキーでデータが保存されている場合は、上書きで更新されるので注意してください。

以下にデータの保存のサンプルを記載します。

// NSUserDefaultsのインスタンスを作成
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// NSString型の「test」を「string_key」のキーに保存
[ud setObject:@"test" forKey:@"string_key"];
// int型の「1」を「int_key」のキーに保存
[ud setInteger:100 forKey:@"int_key"];
// float型の「1.1」を「float_key」のキーに保存
[ud setFloat:1.1 forKey:@"float_key"];
// double型の「1.1」を「double_key」のキーに保存
[ud setDouble:1.1 forKey:@"double_key"];
// BOOL型の「YES」を「bool_key」のキーに保存
[ud setBool:YES forKey:@"bool_key"];
// 保存内容を即時で反映する為に、同期する(この記載がない場合には、即時反映されない)
[ud synchronize];

◾️データの取得

ここでは、NSUserDefaultsのデータの取得方法を記載します。
データの保存で記載したキーを元にデータを取得します。

以下にデータの取得のサンプルを記載します。

// NSUserDefaultsのインスタンスを作成
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// 「string_key」キーの値を取得(NSString型)
NSString s = [ud stringForKey:@"string_key"];
// 「int_key」キーの値を取得(int型)
int i = [ud integerForKey:@"int_key"];
// 「float_key」キーの値を取得(float型)
float f = [ud floatForKey:@"float_key"];
// 「double_key」キーの値を取得(double型)
double d = [ud doubleForKey:@"double_key"];
// 「bool_key」キーの値を取得(BOOL型)
BOOL b = [ud boolForKey:@"bool_key"];

◾️データの削除

ここでは、NSUserDefaultsのデータの削除方法を記載します。
データの保存で記載したキーを元にデータを削除します。

以下にデータの削除のサンプルを記載します。

// NSUserDefaultsのインスタンスを作成
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// 「string_key」キーの値を削除(NSString型)
[ud removeObjectForKey:@"string_key"];
// 「int_key」キーの値を削除(int型)
[ud removeObjectForKey:@"int_key"];
// 「float_key」キーの値を削除(float型)
[ud removeObjectForKey:@"float_key"];
// 「double_key」キーの値を削除(double型)
[ud removeObjectForKey:@"double_key"];
// 「bool_key」キーの値を削除(BOOL型)
[ud removeObjectForKey:@"bool_key"];

◾️キーの存在チェック

NSUserDefaultsのキーの存在チェック

ここでは、NSUserDefaultsのキーが存在するかどうかのチェック方法を記載します。

以下にキーが存在するかどうかのチェック方法のサンプルを記載します。

// NSUserDefaultsのインスタンスを作成
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// 「TargetKey」キーが存在するかどうかを判定する
if([[[ud dictionaryRepresentation] allKeys] containsObject:@"TargetKey"]){
// キーが存在する場合
} else {
// キーが存在しない場合
}