おじゃまぷよ系エンジニアメモ

アプリエンジニアからサーバーとインフラエンジニアに転身しました

knockout.jsでajaxでAPI叩いてモーダル表示分け

とあるqueryパラメーターによって表示するモーダルの内容を変えるのをどうしようかと考えた結果
jQueryajaxAPIを叩いて、受け取ったレスポンスをKnockout.jsを使ってデータバインディングする形に落ち着いた。 モーダルを1つふやすのに、api,js,htmlの3つのファイル修正加えないといけないけど、基本的にif文なり加えて増やせばいいだけなので
そんなに複雑にならないであろうと思っている。 表示、非表示をもう少しうまく切り替えたいけど…

続きを読む

DialogFragmentのshowとdismiss方法はコレに落ち着いた

ちょっと仕事でアプリのクラッシュログがすごい量出てきて調べてほしいと言われてとりあえずFabricのスタックトレースをみてみたら
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState」で落ちまくっている。なんとなく予想はしていたが Fragmentの貼り付けているWebViewのonPageStartedでDialogFragmentをshow()して、onPageFinished()でdismiss()している箇所があり
ここの部分が半端無く落ちてる。まぁそうだろうな…WebViewのロードが終わる前に画面回転とかしたらこのExceptionが発生してそのまま即死コース一直線だ

続きを読む

kotlinでAndroidアプリを試しに作った

よくお世話になるクローディアのアプリのAndroid版をkotlinで書き直し中 最近あまりネイティブアプリを書くことがなくなってきたのでリハビリを兼ねて作ってみました。

とにかく最近のトレンドを追いかけるために

  • retrofit
  • databinding
  • realm
  • rxJava

この辺りは入れてみようと思いましたが、realmだけまだ入れてない。。。
Dagger2もまだ使ったことないので使ってみたかったが後回し
設計もいまトレンドのMVPでActivityを極力Viewの操作のみに専念し
PresenterがRepository層のクラスを使ってAPI通信を行ったり、PreferenceFileに書き込みを行ったりということをしています。少々雑ですが…
更に細かくやると、UseCase層も作ってそこにRepositoryとのやりとりをまとめたほうが抽象度は上がるのでしょうが、個人でやるにはそこまではやりすぎ感があったので
Presenterが色んなRepositoryとやりとりして結果をViewに知らせる形にしました。
テストコードもビジネスロジックはPresenter側に押し込めるのでPresenterを抑えておけばとりあえず大丈夫なはず。
View側のテストはInstrumentテストで頑張ればいいかなぁという感じ。
RepositoryとViewはInterfaceで実装を抽出してPresenterに渡しているのでmockを差し込むのもやりやすくて良かったです。

続きを読む

Androidのアレ!iOSでいうと

メモ書き程度のもの そのうち追加したり、もう少し詳しく書く

画面遷移(startActivity)

Android

Intent intent = new Intent(this,NextActivity.class);
startActivity(intent);

iOS

stroyboardでViewControllerを「Control + ドラッグ」でつなげて SegueのIdentifierを定義する「toNextViewController」

self.performSegueWithIdentifier("toNextViewController",sender:nil)

画面遷移with値(intent.putExtra)

Android

Intent intent = new Intent(this,NextActivity.class);
intent.putExtra("param","hoge");
startActivity(intent);

//NextActivityで
getIntent().getExtras().getString("param") //hoge

iOS

prepareForSegueを使います

class NextViewController:UIViewController{
    var value1:Int = 0
    var value2:String = ""
}
func hoge(){
    self.performSegueWithIdentifier("toNextViewController",sender:nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let nextViewController = segue.destinationViewController as! NextViewController
        nextViewController.value1 = 123
        nextViewController.value2 = "hogehoge"
}

画面から戻ってきたとき(onActivityResult)

Android

public class FugaActivity extends Activity {

    private static final int REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this,NextActivity.class);
        startActivityForResult(intent, REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK && requestCode == REQUEST_CODE){
            //doSomething
        }
    }
}
        

iOS

StoryBorad Unwind segue でググる

pull refresh

Android

AndroidではSwipeRefreshLayoutの中にListViewを入れるのが一般的です

http://developer.android.com/intl/ja/samples/SwipeRefreshListFragment/index.html より

<android.support.v4.widget.SwipeRefreshLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/swiperefresh"
      android:layout_width="match_parent"
      android:layout_height="match_parent">

    <ListView
          android:id="@android:id/list"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        //必要に応じてtrue,falseを設定してあげる
        mSwipeRefreshLayout.setRefreshing(true);
        //何かしらの処理。多くの場合はAPI叩く
    }
});

iOS

tableViewControllerを使わない場合

@IBOutlet weak var tableView: UITableView!
let refreshControl:UIRefreshControl = UIRefreshControl()
override func viewDidLoad() {
    super.viewDidLoad() 
    //pull to refreshで実行するメソッド名を指定します
    refreshControl.addTarget(self, action: Selector("refresh"), forControlEvents: UIControlEvents.ValueChanged)
    tableView.addSubview(refreshControl)
}

func refresh(){
//doSomething
self.refreshControl.endRefreshing()
}

tableViewControllerを使っている場合 storyboardからTableViewのRefreshを「enable」にして

override func viewDidLoad() {
    super.viewDidLoad() 
    self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
}

func refresh(){
//doSomething
self.refreshControl.endRefreshing()
}

これでいける模様

バックグラウンドから復帰したとき

Android

onResumeやonRestartなど、その時の用途にあったライフサイクルを選ぶ

iOS

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/

override func viewDidLoad() {
    let notificationCenter = NSNotificationCenter.defaultCenter()
    //アプリがアクティブになったとき
    notificationCenter.addObserver(
            self,
            selector: "doHoge",
            name:UIApplicationDidBecomeActiveNotification,
            object: nil)
}
func doHoge(){
    //doSomething
}

そのほかにバックグラウンドに移行したときなど、notificaitonのtypeがいろいろあります

リストビューの最下部までスクロールしたときをハンドリング

Android

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (totalItemCount == firstVisibleItem + visibleItemCount) {
            //doSomething
        }
    }
});

iOS

func scrollViewDidScroll(scrollView: UIScrollView) {
   //一番下までスクロールしたかどうか
   if(tableView.contentOffset.y >= (tableView.contentSize.height - tableView.bounds.size.height) && !nowLoading)
    {
        //doSomething
    }
}

アップルの審査との100日戦争

CroudiaというマイナーSNSiOSアプリを作りました。処女作です。
処女作という響きにはロマンが詰まってますね?
初回リリースまでにおよそ8回リジェクトされ、初申請からリリースまで3ヶ月近くかかりました。

ちなみにアプリはこちら

Icros

Icros

  • Masahide Takahata
  • Social Networking
  • Free

その戦いの記録を振り返ってまとめてみます。
ただ、問題解決センターで実際にやりとりした内容が見えなくなってしまったので思い出しながら書くので 多少情報が不明瞭な部分もありますが悪しからず……

続きを読む