読者です 読者をやめる 読者になる 読者になる

忘れん坊のサンタクロース

iOS,Androidアプリ開発についての忘備録です。技術関連情報など掲載していこうかと考えています。時々関係ないことも書くかも。。

小さい画像のImageButtonだとタップ範囲が狭いってときの拡張法

Android

タイトルには拡張とありますが、実際のところ、ImageViewを持つレイアウトにクリックイベントを実装している感じです。

           <RelativeLayout
                    android:layout_width="?attr/actionBarSize"
                    android:layout_height="?attr/actionBarSize"
                    android:onClick="onClickBack">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:layout_centerInParent="true"
                        android:scaleType="fitXY"
                        android:src="@drawable/icon_back" />

                </RelativeLayout>

あとはActivityでクリックイベントを実装してあげれば気持ち良くタップが効いてくれます。

command failed due to signal segmentation fault 11がXcode8で発動、、。

iOS

Swift3への移行が完了しているプロジェクトを開いたときにのcommand failed due to signal segmentation fault 11が出ました。しかもSourceKitServiceが予期しないほげほげで終了してしまう、、。

 

単刀直入に解決策を言うと

$ rm -rf ~/Library/Developer/Xcode/DerivedData

でおっけいです。過去のデバイスデータが悪さをしていたのだろうか?

ひとまず解決ですが。こいつにたどり着くまでにかなりの時間を喰われましたorz

Xcode8,Swift3.0に以降したときの体験談

タイトル通り環境をXcode8,Swift3.0に移行したときの体験談です。しかし、その前に僕は下記の記事を見て悪あがきをしました。

XCode8に移行した際にしたこと(その場しのぎ編) - Qiita

このリンクの内容Xcode8にしたいけどSwift3.0はちょっとまだ、、って人にはお勧めです。

そんなこんなでXcode8には移行できたのですが、やっぱり3.0を使わないと時代に取り残されそうなので重い腰をあげて最新の仕様に対応しました。

 

Xcode8には既存のプロジェクトをSwift3.0に自動で互換してくれる機能があるのですがcocoapods周りのことを考えても絶対にコンパイルは通らないんだろーなと思ってましたが案の定その通りでした。ここで思ったことは移行対応前にGitにプロジェクトあげておくことをお勧めします。かなり。

ゲームでもそうなんですけどやっぱりセーブデータって大事。。笑

 

さぁ、いこう!(移行)

ということでまずは2.3を使用する設定をしているのでこれを解除します。

TARGET->Build SettingにあるUse Legacy Swift Language versionをNoにします。

 

f:id:appera:20161007095250p:plain

 

これを変更するとエラーが吐かれます、、(戦闘態勢)

f:id:appera:20161007095524p:plain

要は[Edit > Convert > To Current Swift Syntax...]からバージョン選べ、はよ。って感じですね。仰せのままに、、

f:id:appera:20161007095818p:plain

Convert to Swift3にチェックを入れてNext!!

その後、自動変換するファイルを選択できる画面が出てくるので選択します。プロジェクトとTest, UITestを選択してcocoapodsでインストールしているライブラリは選択しません。

 

おそらくほとんどの開発者の方はRealmSwiftを使っていると思うのですがこれをSwift3.0に対応するにはpodfileを以下のリンクを参考にしました。

 

blog.ch3cooh.jp

 

これから移行される方は頑張って下さい!
ハマる人はハマるという感じですね、、。

VersionとBuildの文字列を取得する方法する

iOS

実際にアプリをリリースする際、設定画面などにこれらの情報を表示しておきたい場合などに有効な情報だと思います。

VersionとBuildって?

プロジェクトのTARGETSにあるGenetalのIdentityにあるアレのことです。

f:id:appera:20160929153932p:plain

Versionは言わずもがなばアプリのバージョンのことですが、Buildはすでにアップロード済みのアプリをバージョンを上げずに再アップロードする際、Buildの値を上げることでアップロードが可能になります。(VersionとBuildが前回アップロードのものと同じだとダメ)

取得方法

//Versionの文字列
let version: String! = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
//Buildの文字列
let build: String! = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleVersion") as! String

print("\(version)(\(build))")//1.0.0

これを表示すると以下のように表示することができます。

f:id:appera:20160929154009p:plain

人によってはあまり使う場面はないかもしれないですが参考までにどうぞ^ ^

.gitignoreを自動で作成するgiboの使い方

git

まずはgiboをインストールするため以下のコマンドを叩きます。

brew install gibo

brewはパッケージ管理システムの一つであるHomebrewをインストールすることで使用することができます。

その後、インストールが完了したか以下のコマンドで確認してみましょう。

gibo -version

すると以下のように出力されます。

gibo 1.0.4 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo


確認ができたらgibo -lで自動作成できる環境の一覧を表示してみましょう。

gibo -l
=== Languages ===

Actionscript		CUDA			Go			Magento			Qt			Terraform
Ada			D			Gradle			Maven			R			TeX
Agda			Dart			Grails			Mercury			Rails			Textpattern
Android			Delphi			GWT			MetaProgrammingSystem	RhodesRhomobile		TurboGears2
AppceleratorTitanium	DM			Haskell			Nanoc			ROS			Typo3
AppEngine		Drupal			Idris			Nim			Ruby			Umbraco
ArchLinuxPackages	Eagle			IGORPro			Node			Rust			Unity
Autotools		Elisp			Java			Objective-C		Sass			UnrealEngine
C++			Elixir			Jboss			OCaml			Scala			VisualStudio
C			Elm			Jekyll			Opa			Scheme			VVVV
CakePHP			EPiServer		Joomla			OpenCart		SCons			Waf
CFWheels		Erlang			Julia			OracleForms		Scrivener		WordPress
ChefCookbook		ExpressionEngine	KiCad			Packer			Sdcc			Xojo
Clojure			ExtJs			Kohana			Perl			SeamGen			Yeoman
CMake			Fancy			LabVIEW			Phalcon			SketchUp		Yii
CodeIgniter		Finale			Laravel			PlayFramework		Smalltalk		ZendFramework
CommonLisp		ForceDotCom		Leiningen		Plone			Stella			Zephir
Composer		Fortran			LemonStand		Prestashop		SugarCRM
Concrete5		FuelPHP			Lilypond		Processing		Swift
Coq			Gcov			Lithium			Python			Symfony
CraftCMS		GitBook			Lua			Qooxdoo			SymphonyCMS

=== Global ===

Anjuta			Dreamweaver		JDeveloper		Mercurial		Redis			Vim
Ansible			Dropbox			JetBrains		MicrosoftOffice		SBT			VirtualEnv
Archives		Eclipse			Kate			ModelSim		SlickEdit		VisualStudioCode
Bazaar			EiffelStudio		KDevelop4		Momentics		SublimeText		WebMethods
BricxCC			Emacs			Lazarus			MonoDevelop		SVN			Windows
Calabash		Ensime			LibreOffice		NetBeans		SynopsysVCS		Xcode
Cloud9			Espresso		Linux			Ninja			Tags			XilinxISE
CodeKit			FlexBuilder		LyX			NotepadPP		TextMate
CVS			GPG			macOS			Otto			TortoiseGit
DartEditor		IPythonNotebook		Matlab			Redcar			Vagrant


これらの中から作成したい.gitignoreの環境を選び.gitignoreを設置したい場所まで移動して

vi .gitignore

で.gitignoreを作成してから、例えばAndroidStudioなら

gibo -Android >> .gitignore

Xcodeなら

gibo -Xcode >> .gitignore

というようにコマンド叩けば指定した環境の.gitignoreが作成できます。

.gitignoreしてもUserInterfaceState.xcuserstateが無視できない!

git Xcode

Xcodeのプロジェクトにgitを導入した際に、.gitignoreを追加した時のお話し。無視するように.gitignoreを編集してもコミット時に必ず現れるUserInterfaceState.xcuserstate。なんでだ!と思っていたのですが、結論から言うとキャッシュが残っていたからなんですね、、。余計なところでイライラしてしまった。。

$ git rm --cached <プロジェクト名>.xcodeproj/project.xcworkspace/xcuserdata/<ユーザー名>.xcuserdatad/UserInterfaceState.xcuserstate
$ git commit -m "removed cache."

これで二度と奴は出てこない、、ふっふっふ。

Fragmentでのイベントハンドリング

Android

FragmentにButtonを置いてみたけどレイアウトで定義したButtonのonClickがFragmentで実装できないじゃん!!とかいろいろな問題に直面したので頭を冷やして解決方法をメモします。

まず上記の例に関して言えば、そのFragmentを持つActivityで実装することができます。しかし、Fragmentが複数ある場合、FragmentそれぞれのウィジェットをActivityで実装しなければならないというスパゲティのいい匂いがしてきます。つまりはFragmentのイベントはFragmentで処理したいじゃん??、、では解決方法について説明します。

IDでオブジェクトを取得して、リスナーを登録する

これは超簡単!
まずレイアウトで定義したウィジェットのIDからオブジェクトを取得します。
その後、リスナーを登録してあげれば完成です。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = (View)inflater.inflate(R.layout.fragment_main, container, false);

    //IDからオブジェクトを取得
    Button button  = (Button)view.findViewById(R.id.button);

    //リスナーを登録
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.v("button:", "clicked!");
        }
    });

    return view;
}

これでButtonをタップするとログにメッセージが表示されると思います。

アクティビティへのイベントコールバックを作成する

こちらは公式サイトのAPIガイドにある方法なのですが、Activityの何かしらの情報の取得やUIの操作をするのであれば以下のように実装しましょう。

まずはFragmentにInterfaceを定義しましょう。

public class MainFragment extends Fragment {

 //Activityにイベントを通知する役割を持つ
    public interface OnClickListener {
        void onClick();
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_main, container, false);
    }
}

このOnClickListenerをActivityのインターフェースにしてonClickを実装します。

public class MainActivity extends AppCompatActivity implements MainFragment.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onClick() {
        Log.v("onClick:", "想いよ届け");
    }
}

その後、Fragmentに戻ってOnClickListenerの変数をフィールド持ち、Fragmentのライフサイクルの一つであるonAttach()を以下のように実装します。

public class MainFragment extends Fragment {

    OnClickListener _clickListener;

    public interface OnClickListener {
        void onClick();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            _clickListener = (OnClickListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(getActivity().toString() + "must implement OnArticleSelectedListener.");
        }
    }
}

ちなみにonAttach()はFragmentをActivityに追加する際に呼ばれるメソッドです。メモメモ、、。
onAttach()内ではActivityがOnClickListenerを実装しているかをハンドリングし、成功すればそれをフィールドに持つようにしています。これで先ほどのIDでオブジェクトを取得する方法と合わせて、

    //リスナーを登録
 button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                _clickListener.onClick();
        }
    });

これでFragmentのButtonを押した際のイベントがActivityに通知されるようになります。
この方法、Buttonに限らずListViewのタッチイベント(むしろこっちの方が多いかも)などでも使用する場面があると思うのでいろいろと応用がきくと思います。