2010/07/22

このサイトは自作なので、Wordpressみたいなエディタ強化がイマイチです。

tinymceからシンプルエディタをJSで切替る際、どうしてもHTMLタグが挿入されちゃう(>_<)

Wordpressのquicktags.js

とりあえずtinymceは一旦停止して、Wordpressに付属しているquicktags.jsを使ってみました。 インストールされている場所は、

wordpress/wp-includes/js/quicktags.js

これを自分のサイトにコピーしてHTMLヘッダーで読み込み

サンプルコード


     

HTMLタグのツールバーは以下のようにすれば表示される。

  2010/07/21

NSURLDownload

コンテンツをダウンロードしてファイルに保存 これはよくまとまっているサイトが、NSURLDownloadはCocoaフレームワークのものでUIKitにはないようです。

よって、NSURLDownloadをラッパークラスとして使うようです。

iPhone SDKレシピ2:NSURLConnectionを使ってファイルをダウンロードする

NSURLConnection

iPhone UrlConnection を使ってみた

- (void)connection:(NSURLConnection *)i_connection didReceiveResponse:(NSURLResponse *)i_response;
- (void)connection:(NSURLConnection *)i_connection didReceiveData:(NSData *)i_data;
- (void)connectionDidFinishLoading:(NSURLConnection *)i_connection;
- (void)connection:(NSURLConnection *)i_connection didFailWithError:(NSError *)i_error;

  2010/07/21

CoreDataを使うまでもなく手っ取り早く設定を保存したい場合は、SettingsBundleを利用すると便利かも。

手順

(1) 新規ファイル > ResourceでSettings Bundleを選択し、Settings.bundledで保存

(2) Settings.bundle > Root.plistを開く

(3) PreferenceSpecifiersを開き、各項目の設定 item0:グループ item1:ユーザ名 item2:パスワード として作成した。

(4) Settingsを読み込む
※viewDidAppearで設定した 

- (void)viewDidAppear:(BOOL)animated {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];;
    [super viewDidAppear:animated];
}

(5) アプリを起動して、設定を確認してみる。

これだけ。 スライダーや階層型で設定する事も可能です。 AndroidもXMLで設定する感じで素晴らしいと思ったけど、Xcodeも素晴らしいよ。

  2010/07/16

えっと、iPhone参考本でついにQuartzの章にはいりましたが、いきなり話を脱線してQuartz Composerについて。

Xcodeをインストールすると「Quartz Composer」てのがもれなく付属してます。 ただ書籍も持ってないしチンプンカンプンなので、ネットで検索してみた。

Quartz Composerによるビジュアルフロープログラミング

「Quartz Composer」はiPhoneはもとより、JavaScriptに対応しているみたいです。 ・Snow Leopard対応!初めてのQuartz Composer入門Quartz Composer×JavaScriptでRSSリーダーを作ろう

つまりは、Adobeのオーサリングツールみたくアニメーション作成できるわけっすね。 そしてアニメーションに限らず、OSCを使ったMIDIやWifi通信、ビデオカメラとか色んなライブラリが使えるようです。
ライブラリのカテゴリだけでこんなに!

こんな感じでパッチをつないで、ノンコーディングで作成していきます。

QuickTimeで書き出してみました >>サンプル動画

Windowsだとコーデックの関係か?デフォでみれない

みたいなので、キャプチャーを

Quartz Composerのマニュアルは例のごとくAppleから(苦) Apple Developer Quartz Composer

  2010/07/16

どこでもセーブ永続化が必要ならNSCoding Protocolを実装する の記事ように、NSKeyedArchiverとNSKeyedUnarchiverでデータをシリアライズしてファイル保存できる。

ポイントはNSCodingプロトコルを実装する事。 手軽なデータ保存アプリにはいいかも。 また履歴の保存とか面倒なデーター群をシリアライズして1つのフィールドに格納するのに便利かな?

逆にデータの一部分だけ取り出したいとか、検索が絡んでくると大変な気もする。。。 実際に使ってないので、あくまでも机上の空想だがw

  2010/07/15

CoreDataの基礎 その1|CoreDataの基礎 その2|CoreDataの基礎 その3|CoreDataの基礎 その4

実際にデータを保存してみる。

結論から言ってハマりました。。。

まず、.xcdatamodelでのEntityの設定で以下のようにしました。

・Entity名:User ・アトリビュート キー:no int16 氏名:name String

で、ですね、「SELECT * FROM User WHERE no = 2;」みたいなことをやろうと、

NSPredicate *pred = [NSPredicate predicateWithFormat:@"(no = %d)", i];

を実行してもまったくもって抽出できない! 文字列のフォーマットが駄目なのか?と何度も検証したが何度やってもうまくいかないorz で、判明したのが、

アトリビュート名で「no」を使うと抽出できなかった・・・

SQLiteの予約語なのか?Core Dataで利用できないのか?わからないが、アトリビュート名を 「no」→「id」に変更したらうまくいきました。 ※idはObjective-Cの予約語なのでこれも命名的によろしくないとは思いますが・・・

サンプル

駄目駄目なかなり汚いコードですが・・・まぁ、調査と言う事で。

- (void)applicationDidEnterBackground:(UIApplication *)application {
    Core_Data_persistenceAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSError *error;
    
    for (int i = 1; i <= 4; i++) {
        NSString *fieldName = [NSString stringWithFormat:@"line%d", i];
        UITextField *textField = [self valueForKey:fieldName];
        
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
                                                             inManagedObjectContext:context];
        [request setEntity:entityDescription];
        
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"(id = %d)", i];
        [request setPredicate:pred];
        
        NSManagedObject *user = nil;
        NSArray *objects = [context executeFetchRequest:request error:&error];

        if (objects == nil) {
            NSLog(@"Error!");
        }
        if ([objects count] > 0) {
            //UPDATE
            user = [objects objectAtIndex:0];
        } else {
            //INSERT
            user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
                                                 inManagedObjectContext:context];
        }
        
        [user setValue:[NSNumber numberWithInt:i] forKey:@"id"];
        [user setValue:textField.text forKey:@"name"];
        [request release];
    }
    [context save:&error];
}

- (void)viewDidLoad {
    NSLog(@"viewDidLoad");
    Core_Data_persistenceAppDelegate *appDelegate =
    [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
                                                         inManagedObjectContext:context];
    [request setEntity:entityDescription];
    
    NSError *error;
    NSArray *objects = [context executeFetchRequest:request error:&error];
    [request release];
    if (objects == nil) {
        NSLog(@"Error!");
    }
    for (NSManagedObject *oneObject in objects) {
        NSNumber *rid = [oneObject valueForKey:@"id"];
        NSString *name = [oneObject valueForKey:@"name"];
        UITextField *textField = [self valueForKey:fieldName];
        textField.text = name;
    }
    
    UIApplication *app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] 
     addObserver:self
     selector:@selector(applicationDidEnterBackground:)
     name:UIApplicationDidEnterBackgroundNotification
     object:app
     ];
    [super viewDidLoad];
}

保存処理の流れ

(1) applicationDidEnterBackgroundが呼び出される (2) ApplicateionDelegateからNSManagedObjectContextを取得 (3) NSEntityDescription entityForNameでUser Entityを取得 (4) データベースリクエストである (5) NSFetchRequest setPredicateでクエリーを設定

SELECT * FROM User WHERE id = %d

(6) (NSArray *) NSManagedObjectContext executeFetchRequest:NSFetchRequestでクエリー実行 (7) 既にデータがある場合はNSArrayの最初のデータ(NSManagedObject)取得 (8) データがない場合はNSEntityDescription insertNewObjectForEntityForNameでNSManagedObjectを新規作成 (9)setValueで各値を設定し、NSManagedObjectContext saveで保存

読み込み処理の流れ

(1) viewDidLoadが呼び出される (2) ApplicateionDelegateからNSManagedObjectContextを取得 (3) NSEntityDescription entityForNameでUser Entityを取得 (4) NSFetchRequest setPredicateでクエリーを設定 (5) (NSArray *) NSManagedObjectContext executeFetchRequest:NSFetchRequestでクエリー実行 (6) NSArrayをループして、valueForKeyでデータ設定

また、viewDidLoadでapplicationDidEnterBackgroundのObserverを設定しています。 ただ、Applicationの遷移でデータを制御するのは危険かと思うのであくまでも一例で・・・

  2010/07/15

iOS4になってマルチタスクになりましたが、起動・終了・サスペンドの処理の仕様が変更になっています。

参考本でアプリ終了時(iPhoneのホームボタンで終了時)にデータ保存するサンプルがあるんですけど、その通りコーディングして実行しても、データが保存されません。

もっと詳しく言うと、

(1) viewDidLoadが呼ばれ、NSNotificationCenterのObserverdでapplicationWillTerminateを登録 (2) iPhoneのホームボタンをクリック(アプリ終了ではない) (3) applicationWillTerminateは呼ばれない
※参考本ではapplicationWillTerminateで保存処理を書いている (4) データが保存されない

つうわけで、NSLogでUIApplicationのDelegateメソッドを追ってみました。 ■アプリケーション起動時

(1) didFinishLaunchingWithOptions (2) UIViewController loadVIew (3) UIViewController viewDidLoad (4) UIViewController viewWillAppear (5) UIViewController viewDidAppear (6) applicationDidBicomActive

■ホームボタンクリック

(1) applicationWillResignActive (2) applicationDidEnterBackground

■再度ホームボタンクリック

(1) applicationWillEnterForeground (2) applicationDidBecomeActive

となります。

つまりマルチタスクのiOS4では自動でapplicationWillTerminateが呼ばれない! のでapplicationWillResignActiveかapplicationDidEnterBackgroundに保存処理を書くか・・・。

まぁユーザに明示的に保存させるのが必須ってことですね。 でもさ、でもさ、XcodeでCore Dataプロジェクト作成すると

デフォルトでapplicationWillTerminateにCore Dataの処理が記述されてる(??)

どっちなのApple?・・・まぁ、マルチタスクじゃない方を優先してるんだろうけどw

以前にも書きましたが、やはりマルチタスクは鬼門なのでiOS4 アプリケーションの状態遷移を参考にしてアプリを作っていった方が良いです。

ちなみに、iPhoneのホームボタンをダブルクリックするとバックグランドで待機しているアプリ一覧が表示されます。 これは気づかなかったw
てか、全てのアプリが待機状態になっています。 マルチタスクってのはこういうことだったのか・・・真のマルチタスク(?)じゃないのね。

  2010/07/14

検索してたら、Objective-Cのメモリ管理について記載があったのでメモ書きというか、コピーw AppleDevelopper メモリ管理

<

p class="code">新しいオブジェクトに動的にメモリを割り当てる 新たに割り当てられたメモリを適切な値に初期化する 2 つのステップを完了するまで、オブジェクトは完全には機能しません。 各ステップを実行するのは別々のメソッドですが、通常は 1 行のコードに記述します。

id anObject = [[Rectangle alloc] init];

NSObject では 2 つの主要なメソッド、allocとallocWithZone:を定義しています。

+ (id)alloc; + (id)allocWithZone:(NSZone *)zone;

メソッドが引数を持たない場合、メソッド名はそれらの 4 文字のみ、つまりinitになります。 引数を持つ場合、「init」プレフィックスの後に引数のラベルが続きます。

たとえば、NSView は initWithFrame: メソッドで初期化することができます。 init...メソッドは新たに割り当てられたレシーバ以外のオブジェクトを返すかnil を返すことがあるため、プログラムでは alloc または allocWithZone: が返す値だけでなく、初期化メソッドが返す値を使用することが重要です。

次のコードは init が返す値を無視しているため、非常に危険(らしい)です。

例1

id anObject = [SomeClass alloc];
[anObject init];
[anObject someOtherMessage];

この代わりに、オブジェクトを安全に初期化するには、割り当ておよび初期化メッセージを 1 行のコードに結合する必要があります。

例2

id anObject = [[SomeClass alloc] init];
[anObject someOtherMessage];

  2010/07/14

Photosにスライドショーとサムネイル切替をつけてみた。

スライドショーは、jQueryライブラリであるCrossSlide を利用。 ■HTMLヘッダー





■JavaScript(汎用化)


var photos = new Array();
//初期化
function slideInit() {
    $('#display').crossSlide({ sleep: 3, fade: 2 }, photos);
}
//スライド開始
function startSlide() {
  $("#photo").hide();
  $("#display").fadeIn("slow");
  $("#display").crossSlideRestart();
}
//スライド停止
function stopSlide() {
  $("#display").crossSlideStop();
  $("#display").fadeOut("slow");
}
//photos配列インデックスから写真表示
function showPhoto(index) {
  stopSlide();
  var photo = photos[index];
  $("#photo").fadeOut("slow");
  $("#photo").attr("src", photo);
  $("#photo").fadeIn("slow");
}

「var photos」とグローバルにしてるのが、ちょっと危ないけどw

■JavaScript(実行) ※PHPで動的に写真配列をJavaScript出力


$(function() {
    loadPhotos();
    slideInit(); 
});

function loadPhotos() {                
    photos.push({src:'http://colinux/yoo_blog/images/photos/22.jpg', dir:'up'});                   
    photos.push({src:'http://colinux/yoo_blog/images/photos/21.jpg', dir:'down'});           
    photos.push({src:'http://colinux/yoo_blog/images/photos/20.jpg', dir:'up'});                     
    photos.push({src:'http://colinux/yoo_blog/images/photos/9.jpg', dir:'down'});  
}

データ生成処理は、Ajaxで非同期通信してデータで処理するのもありかも。

■HTML(データ生成&実行) ※PHPで写真配列をアウトプット


Slide Show 

スライドショーは、予め写真を先読みしておいて(このサイトではPHP)画像配列を設定しています。

$(id).crossSlide(オプション、画像配列)

これで指定したidのエレメントにスライドショーが表示される。 画像取得は、JSONで取得した方がJS側で応用がききそうですが、まぁ時間があれば。スライドショー停止はcrossSlideStop()、リスタートはcrossSlideRestart()を直接呼ぶだけ。 ※詳しくは、CrossSlide のページを参照

手動切替は、jQuery標準のfadeIn、fadeOutを利用。 写真を先読みして配列にしておいて、indexで切り替えるだけです。

$(id).attr("src", photos[index]);

  2010/07/14

SQLite3を直接使うには、フレームワーク「libsqlite3.bylib」の追加が必要。

Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.0.sdk/usr/lib/

フレームワークを追加したら.hにsqlite3をimportしておく。

#import "/usr/include/sqlite3.h"

.mに実装する。 ■データベース作成

    if (sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(0, @"Faild to open database");
    }
    
    char *errorMsg;
    NSString *createSQL = @"CREATE TABLE IF NOT EXISTS FIELDS (row INTEGER PRIMARY KEY, field_data TEXT);";
    
    if (sqlite3_exec(database, [createSQL UTF8String], NULL, NULL, &errorMsg)) {
        sqlite3_close(database);
        NSAssert(0, @"Error creating table: %s", errorMsg);
    }
    NSString *query = @"SELECT row, field_data FROM FIELDS ORDER BY row";
    sqlite3_stmt *stmt;
    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            int row = sqlite3_column_int(stmt, 0);
            char *rowData = (char *)sqlite3_column_text(stmt, 1);
            
            NSString *fieldName = [[NSString alloc]
                                   initWithFormat:@"field%d", row];
            NSString *fieldValue = [[NSString alloc] initWithUTF8String:rowData];
            UITextField *field = [self valueForKey:fieldName];
            field.text = fieldValue;
            [fieldName release];
            [fieldValue release];
        }
        sqlite3_finalize(stmt);
    }

■データ挿入/更新

-(void)applicationWillTerminate:(NSNotification *)notification {
    for (int i = 1; i <= 4; i++) {
        NSString *fileName = [[NSString alloc]
                              initWithFormat:@"field%d", i];
        UITextField *field = [self valueForKey:fileName];
        [fileName release];
        char *errorMsg;
        char *update = "INSERT OR REPLACE INTO FIELDS (ROW, FIELD_DATA) VALUES(?, ?);";
        sqlite3_stmt *stmt;
        if (sqlite3_prepare(database, update, -1, &stmt, nil) == SQLITE_OK) {
            sqlite3_bind_int(stmt, 1, i);
            sqlite3_bind_text(stmt, 2, [field.text UTF8String], -1, NULL);
        }
        if (sqlite3_step(stmt) != SQLITE_DONE) {
            NSAssert1(0, @"Error updating table: %s", errorMsg);
            sqlite3_close(database);
        }
    }
}

SQLite3で利用できるメソッドやプロパティー等は、sqlite3.hを参考にすればよい。 基本的にデータベース作成、SQL実行なので、SQLがわかればそんな難しいことはないと思う。 ※sqlite3に関わる構文上で、option + クリック

ソース

pngファイルの軽量化
Google DriveのIconを再起的に削除
php-markdownでバニラPHPなコードブロック処理
laravel-ffmpeg を使う
2021年版 Ubuntu + certbot + Let's Encrypt でサーバ証明書設定
GihHub のデフォルトでない master ブランチを checkout する
マルチログインで未認証のリダイレクト
Homebrew で Redis をインストール
CSS だけでスムーズスクロール
EC-CUBE4 で Gmail の smtp を利用する
Amazon Linux 2 の amazon-linux-extras とは
UNIQUE カラムのバリデーションで自分自身を除外して更新
フォーム有効期限切れで Page Expired をリダイレクト
ログを日付でローテーションやクリアや削除
Homebrew で PHP8.0 から PHP7.4 にダウングレード
Big sur で zsh 移行と Homebrew アップグレード
Mac に minikube をインストール
途中から .gitignore に追加する
Larevel 6.x から Laravel 8.x にバージョンアップ
Composer で Allowed memory size (メモリ不足)エラー
Blade でカスタムクラスを利用する
git push git pull にブランチ指定せずに実行する
git pull や git push できなくなったとき
Docker のコンテナからホストOS に接続
Mac で ローカル IP アドレス(ipv4)のみを表示する
ホストOS から Docker の MySQLコンテナに接続
caching_sha2_password のエラー
node-config で環境設定ファイルを利用する
rootパスワードを初期化(再設定)する
Git から clone したときのエラー対処
Mac に MySQL をインストール
Mac に PostgreSQL をインストール
Laravel 環境構築 - Mac ネイティブ編
Firebase 入門 - Firebase とは
Firebase 入門 - CLI インストールとデータベースの設定
AWS 無料枠(t2.micro)で容量とメモリエラー
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証