2011年12月14日水曜日

[iOS]CoreDataで検索結果が取得できないバグ

CoreDataを使用したアプリを作成中に

検索結果が取得できないという現象が起きた
発生状況として
検索A>検索B>検索Aとすると結果が取得できない
検索B>検索A>検索Aとすると結果が取得できない
検索A>検索A>検索Aとすると結果が取得できる
検索A>検索C>検索Aとすると結果が取得できる

結果として検索条件を変えることで取得ができるようになった
変更前
NSString *predStr = @"number == '1'";
NSPredicate *pred = [NSPredicate predicateWithFormat: predStr];
変更後
NSString *predStr = @"number == 1";
NSPredicate *pred = [NSPredicate predicateWithFormat: predStr];


シングルクォートを外しただけ
numberは数値方(Int32)なので「そらそうだ」と思ったが
検索の順番を変更すると取得できたりできなかったりするのが謎

2011年12月7日水曜日

[AndroidSDK]iPhoneのナビゲーションバー、ツールバーっぽいバー

toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <!-- ナビゲーションバー、ツールバーのカラー -->
    <gradient

        android:startColor="#FFFFFF"
        android:centerColor="#FF0000"
        android:endColor="#FFFFFF"
        android:angle="270"
    />
    <size

        android:height="40dp"
    />
</shape>


main.xml

    <!--ナビゲーションバー-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:background="@layout/toolbar"
        >
    </LinearLayout>

「戻る」ボタンが欲しい時はLinearLayoutの中に入れればいい

ところでandroidのこのxmlの形式
どこで改行を入れるか、段落区切りはどうするか?という問題がある
まともにXML準拠すると非常に運用しにくい
UIで扱うGraphical Layoutはまともに使えないしね

なのでこの記事でのXML表記はかなり適当になっている。

2011年12月2日金曜日

[AndroidSDK]android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed

AndroidのSqliteで以下のエラーが発生した。

android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed

条件が誤っています、ということで、
Primary keyに重複した値を入れていた、型エラー、カラム名の間違いとかでも出るかもしれない。

クエリが長く原因がわかりにくい時は、一度AndroidからDBをPCに持ってきて
SQLite Managerなどで条件文を確認すると原因が分かりやすいかも

2011年12月1日木曜日

[AndroidSDK]JSONの書き込み

JSONを使用すると、アプリの細かな情報を簡単にストレージに保存できる
iPhoneでいうところplist的な扱いができる
やたらソース長いので短くしたいところ

//ファイルの有無を確認
FileInputStream fileInputStream;
JSONObject jsono = null;
try {
    fileInputStream = openFileInput("profile.json");
    int size = fileInputStream.available();
    byte[] buffer = new byte[size];
    fileInputStream.read(buffer);
    fileInputStream.close();
    String jsnoString = new String(buffer);
    jsono = new JSONObject(jsnoString);
   
} catch (FileNotFoundException e) {
    log("FileNotFoundException "+e);
    //ファイルが存在しないので作成する
    try {
        jsono = new JSONObject();
        jsono.put("hogeInt", 2);
        jsono.put("hogeBool", false);
        jsono.put("hogeString", "foo");
       
        try {
            //ファイルを書き込む
            FileOutputStream fileOutputStream;
            fileOutputStream = openFileOutput("profile.json", MODE_PRIVATE);
            String value = jsono.toString();
            fileOutputStream.write(value.getBytes());
            fileOutputStream.close();
           
        } catch (FileNotFoundException e1) {
            log("FileNotFoundException "+e1);
           
        } catch (IOException e1) {
            log("IOException "+e1);
        }
       
    } catch (JSONException e1) {
        log("JSONException "+e1);
    }
} catch (IOException e) {
    log("JSONException "+e);
   
} catch (JSONException e) {
    log("IOException "+e);
}

try {
    jsono.put("hogeBool", true);
} catch (JSONException e1) {
    log("JSONException "+e1);
}

//ファイルを書き込む
try {
    FileOutputStream fileOutputStream;
    fileOutputStream = openFileOutput("profile.json", MODE_PRIVATE);
    fileOutputStream.write(jsono.toString().getBytes());
    fileOutputStream.close();
   
} catch (FileNotFoundException e1) {
    log("FileNotFoundException "+e1);
   
} catch (IOException e1) {
    log("IOException "+e1);
}

2011年11月28日月曜日

[AndroidSDK]ListViewの行間を開けて透過にする

//リストの作成
ListView listView = new ListView(this);
//行間の透過Drawbleを設定
ColorDrawable sage = new ColorDrawable(Color.argb(000, 255, 255, 255));
listView.setDivider(sage);
//行間の高さを設定
listView.setDividerHeight(10);

参考 efreedom.com

2011年10月7日金曜日

[AndroidSDK]ImageViewがうまく動かない

追記
注意:この方法では複数デバイスに対応出来ない。


結論から言うと
横幅がを合わせたいときは
android:adjustViewBounds="true"
を使用する。



2011年10月5日水曜日

[AndroidSDK]Internal Error (classFileParser.cpp:3494)

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (classFileParser.cpp:3494), pid=3508, tid=560
#  Error: ShouldNotReachHere()
#
# JRE version: 6.0_26-b03
# Java VM: Java HotSpot(TM) Client VM (20.1-b02 mixed mode windows-x86 )
# An error report file with more information is saved as:
# C:\MyProgram\AndroidSDK\Atlas500\hs_err_pid3508.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

AndroidSDK+eclipceで上記のエラーが発生した場合は、
メニューのRun>RunconfigがJavaApplicationになっているので
AndroidApplicationに変更する。

まあ当たり前といえば当たり前なのかもしれない、、、

2011年9月27日火曜日

[iOS]Coredataでデータを取り出すときの注意

Coredataを使用して内容を取り出す時に

value = [[manageObject valueForKey:@"mydata"];

とすると、DBのポインターを引っ張ってきてしまうのようなので
このvalueをreleseするとDBを壊してしまう

value = [[manageObject valueForKey:@"mydata"] description];
descriptionをつけることで文字列で取り出すことができる

数値で取り出したときはintValueを使用する

2011年9月26日月曜日

CoreDataを利用したヘッダーとセクションインデックスの使用法

iOSでTableViewのヘッダーとセクションインデックスを指定するときに、
CoreDataを使用するとコーディングが楽になります。

sectionNameKeyPathに設定したいヘッダー、セクションインデックスを指定する

NSFetchedResultsController *_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];

ヘッダーの設定
セクションごと文字列を返す


//ヘッダーを設定する
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    //nameがsectionPathで指定した文字列になる
    return [[[fetchedResultsController sections] objectAtIndex:section] name];
}

セクションインデックスはテーブル作成時に配列で返す

//セクションインデックスを設定する
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    NSMutableArray *indexTitleArray = [[[NSMutable Arrayalloc] init] autorelease];

    for (int i = 0; i < [[fetchedResultsController sections] count]; i++) {
        //nameがsectionPathで指定した文字列になる
        NSString *indexString = [[[fetchedResultsController sections] objectAtIndex:i] name];
        [indexTitleArray addObject:indexString];
    }
    return indexTitleArray;
}

2011年9月21日水曜日

OpenOfficeでファイルロック

他に編集しているユーザーがいない、または編集しているのが自分だけなのに

[filename]は次の人が編集のためロックされています。

というメッセージが表示され、
ロックを解除するにはキャッシュファイルを削除する必要がある

コンソール上で
$ defaults write com.apple.finder AppleShowAllFiles TRUE
$ killall Finder
を行い、隠しファイルを表示させる。

対象ファイルと同じフォルダに対象ファイルと似た名前に隠しファイルがあるので削除
これでロックが解除される。

原因は編集中(OpenOfficeでそのファイルを開いている)に対象ファイルをコピーすると、こうなるそうだ

MACで隠しファイルを表示する方法

・表示
$ defaults write com.apple.finder AppleShowAllFiles TRUE
$ killall Finder


・非表示
$ defaults write com.apple.finder AppleShowAllFiles FALSE
$ killall Finder

2011年9月16日金曜日

plistの読み出し書き出し

plistで読み出しNSDictionaryで格納する。

NSDictionaryは非常に便利。

無題ノート
NSMutableDictionary *appDict;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *path = [paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:@"app.plist"];

if ([[NSFileManagerdefaultManager] fileExistsAtPath:path]) {
    NSMutableDictionary *appDict = [NSDictionarydictionaryWithContentsOfFile:path];
    //何かの処理
    [appDict writeToFile:path atomically:YES];
} else {

}

2011年8月24日水曜日

[iOS]画面を更新

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]];

のはずなんだけどできない


2011/09/21
追記

起動中(はじめのViewの処理が終わるまで)は無効っぽい

2011年8月19日金曜日

NSXMLParserで要素名、内容、属性、属性値を取得する

  • 要素名

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
                                        namespaceURI:(NSString *)namespaceURI
                                       qualifiedName:(NSString *)qName
                                          attributes:(NSDictionary *)attributeDict

要素名 = elementName


  • 内容

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

内容 = string


  • 属性と属性値

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
                                        namespaceURI:(NSString *)namespaceURI
                                       qualifiedName:(NSString *)qName
                                          attributes:(NSDictionary *)attributeDict
attributeDictのkey = 属性
attributeDictの中身 = 属性値

2011年7月13日水曜日

[iOS]Symbol(s) not found for architecture i386

Undefined symbols for architecture armv7:  "_OBJC_CLASS_$_xxxxxxxxxx", referenced from:
または
Undefined symbols for architecture i386

というエラーはクラスがビルド対象になってないこととがある。

XCode4だと
Target > Build Phases > Compile Sources > "+"をクリックして対象のファイルを追加。

また@implementation@interfaceの名称が誤っている時も発生する。

2011年7月4日月曜日

[AndroidSDK]LayoutXMLを使用しないでウィジェットクラスを配置する

//Buttonを作成
Button button = new Button(this);
button.setText("MyText");
button.setOnClickListener (new OnClickListener() {
    @Override
    public void onClick(View v) {
        //TODO クリック動作
    }
});
//Viewに追加
MyLayout.addView(button);

よく使うコード
Gravityの設定
linearLayout.setGravity(Gravity.CENTER);

スケールタイプの設定
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

表示非表示の設定
view.setVisibility(View.GONE);

View使い時にサイズを設定
linearLayout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));

2011年6月27日月曜日

[AndroidSDK]タイトルバーとステータスバーの削除

//タイトルバーの削除
requestWindowFeature(Window.FEATURE_NO_TITLE);

//ステータスバー削除
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

//setContentViewはバーの非表示より後でなくてはいけない
setContentView(R.layout.image_view);

2011年6月23日木曜日

[AndroidSDK]iPhoneツールバーボタンのようなButtonハイライト方法

ボタンとbutton_highlightを重ねるので
iPhoneのツールバーボタンと同じグラフィックになります

//ボタンタップ時のハイライト
ImageView rightButton = (ImageView) findViewById(R.id.light_button);
rightButton.setOnTouchListener(new OnTouchListener() {
 @Override
 public boolean onTouch(View v, MotionEvent event) {
  log("onTouch");
  ImageView image = (ImageView)v;
  switch (event.getAction()) {
  case MotionEvent.ACTION_MOVE:
   break;
   
  case MotionEvent.ACTION_DOWN:
   //ハイライト開始
   image.setBackgroundResource(R.drawable.button_highlight);
   break;
   
  case MotionEvent.ACTION_UP:
   //ハイライト解除
   image.setBackgroundColor(00000000);
   break;
   
  default:
   break;
  }
  return false;
 }
});


2011年6月22日水曜日

[AndroidSDK]LVL証明書の有効時間を変える方法

LVL証明書の有効時間を変える方法
package com.android.vending.licensing
を導入して
ServerMangerPolicy.java

processServerResponse
メソッド
//setValidityTimestamp(extras.get("VT"));
これを変更
setValidityTimestamp(String.valueOf(System.currentTimeMillis() + MILLIS_PER_MINUTE * 60 * 24 *7)));

MILLIS_PER_MINUTE = 1秒

この場合は7日の有効期間。

これだと、サーバーのデータを書き換えてるだけなんだよな。
ClientMangerにするのがベスト。