PHPから始めるメリット・デメリット

まず自分のポジションとしてはPHPでIT業界で働き始めて10年以上経過。
今もかなりPHPにお世話になっています。

メリット
・直感的にわかりやすい。挫折しずらい
・ネット上にサンプルコードが多いのでやりたいことがすぐ実現できる。
・挫折しずらいので時間をかけてWeb周辺の知識も得られる

デメリット
・アプリ等に手を出した時にPHPよりはるかにネット上での情報が少ないので挫折しやすい。
PHPメインの会社に就職すると全体的に緩いので成長しずらい(気がする)

ビジネス指向というかWebでアイデアを実現したい人には1番いいと思う。
将来的に技術を高めて食べて行きたいならPHPはおすすめできないかな。

ふと思ったので書きました、以上です

【ansible】hello world

はじめに

ずっと前から使おうと思って概要とかは見てたけど実際使ったことはありませんでした。
今回実際に案件で使ってみようと思って実際にいじってみました。

簡単で手軽なのをみんな謳っている感じだったのでまぁつまることもないだろうと思ってたのですが、若干時間かかりました。
で、とりあえず自分のPCからVPSAWSへ実行してみる形を想定して手を動かして見ました。

実際に動かす

Macでの作業で今回はvagrant上のサーバへ実行してみました。
とりあえず最低限知っておいた方がよさそうなキーワードは以下

インベントリファイル
意味的にはhostsファイルみたいな感じ。使用したいサーバーはとりあえずここに書かないとダメ。
自分的には.ssh/configのHostに書いてるものを書くと解釈したらスッキリした。

playbook
手順書みたいなもの。手順書だと実際にコマンドを書くけど、ansibleのモジュール(方言)使って記述する感じ。

以下の.ssh/configの場合の例
.ssh/config

Host vagrant_web
  HostName 192.168.33.10
  Port 22
  User vagrant
  IdentityFile path/to/秘密鍵

vagrantの場合、秘密鍵とかあんまり意識しないけどvagrant ssh-configでIdentityFileで確認できる

hosts(インベントリファイル)

vagrant_web

set_timezone.yml(playbook)

- hosts: vagrant_web
  user: vagrant
  become: true
  tasks:
    - name: set timezone
      command: cp /usr/share/zoneinfo/Japan /etc/localtime
    - name: set timezone
      copy: content='ZONE="Asia/Tokyo"' dest=/etc/sysconfig/clock

実行する

$ ansible-playbook -i ./hosts ./set_timezone.yml

何にはまったのか
いろんなサイト見てたらインベントリファイルは/etc/ansible/hostsに書いてる。けどMacだとそれがなかったから。
実際はオプションiを使えばファイルを指定できる。

ヘルプみるとそもそもデフォルトの場所もosによって違うみたい。

$ ansible -h
-i INVENTORY, --inventory-file=INVENTORY
 specify inventory host path
 (default=/usr/local/etc/ansible/hosts) or comma
 separated host list.

タイトルはhello worldだけどhello world出てこなかった。。。
以上です

【xcode】プロジェクト名を変更するのが思ったより面倒だったので手順まとめておく

はじめに

アプリ名とかを仮のまま開発を進めて途中でアプリ名が決定。
プロジェクト名などが旧名称のままだと気持ち悪いのでプロジェクト名を変更したかったのでその時の手順をまとめておきます。

今回は以下の名前をで変更します。
変更前:SampleOld
変更後:SampleNew

とりあえず動くようにする

プロジェクト名を変更

xcodeの[Identity and Type]から「SampleOld」→「SampleNew」に変更。
赤枠の箇所をすべて修正すればたぶんOK
f:id:yoppy0066:20170121000555p:plain

Cocoapods修正

Podfileにプロジェクト名の記述があるので修正

Podfile

target 'SampleNew' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    use_frameworks!
    # Pods for SampleNew
    pod 'AFNetworking'
    ・・・

    target 'SampleNewTests' do
      inherit! :search_paths
      # Pods for testing
    end

    target 'SampleNewUITests' do
      inherit! :search_paths
      # Pods for testing
    end
end

インストールし直す

$ pod install
Bridging-Header.h修正

まずはリネーム
SampleOld-Bridging-Header.h →Sample New-Bridging-Header.h

設定も修正
f:id:yoppy0066:20170121000710p:plain

ここまででビルドとかは問題なくできるようになった。
しかしプロジェクトの中を見るとわかるが実際のフォルダ名はSampleOldのままで気持ち悪い。

旧プロジェクト名を完全になくす

プロジェクトディレクトリ直下に
SampleOld、SampleOldTests、SampleOldUITestsというフォルダが残っているのでそれぞれSampleOld => SampleNewにリネーム

テキストファイルの文字列を置換
find . -path "./.git" -prune -o -type f -print | perl -nle 'print if -f && -T' | xargs sed -i "" "s/SampleOld/SampleNew/g"
バイナリファイルの文字列を置換

バイナリファイルの置換とかやり方わからなかたったので、数も多くないのでviで直接編集した。

検索

$ find . -path "./.git" -prune -o -type f -print | xargs grep "SampleOld" 2> /dev/null
Binary file ./SampleOld.xcworkspace/xcuserdata/xxx.xcuserdatad/UserInterfaceState.xcuserstate matches
・・・

ファイル編集

$ vi -b ./SampleOld.xcworkspace/xcuserdata/xxx.xcuserdatad/UserInterfaceState.xcuserstate
・・・
:%s/SampleOld/SampleNew/g # 全置換して
:wq! # 保存
missing from working copy

git、svnを使ってる場合、ビルドすると上記のワーニングが出る。
コミットすると消えるらしい

さいごに

とりあえずここまでやったらちゃんと動いてる感じ。
今後何も起きないことを祈ります。以上です

以下、参考にさせて頂きました
findで特定のディレクトリを検索対象外(除外)にする - hogehoge foobar Blog Style5
findでテキストファイルのみ抽出 - Qiita

【android】Fragment + ListViewでのAPIへのリクエストのタイミングについて

はじめに

今回やりたかったことは以下
APIから取得したデータをFragment上のListViewへセット
・ListViewのセルをタップしたら詳細画面へ遷移
・詳細画面で戻るボタンでListViewへ戻る

これだけと思ってたら1日はまってしまった。
何にはまったかというと詳細画面から戻った時にAPIへ再度リクエストしていた。

これの解決策がなかなか出てこなかった。。。
そもそもFragmentのライフサイクルとか全然頭になかったところからスタートだったので色々と知識不足

解決策

http://qiita.com/ymd_aaa/items/d04d174fef98c93ef593
中々みつからなかったがまさにここに求めていた答えがありました。

APIリクエストしてデータの取得してアダプタへのセットをonCreateViewメソッドで行なっていたのですが。
これをonCreateメソッドで行うようにすれば戻ってきた時にデータの再取得は行わずやりたいことができました。

処理イメージ

public class MyFragment extends Fragment {

    private ArrayList<UserData> userDataList;
    private UserDataAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // データの初期化                                                                                                                                                                                  
        userDataList = new ArrayList<>();
        adapter = new MuserDataAdapter(getContext(), 0, userDataList);

        // ★ここでAPIコールしてレスポンスをアダプタにデータをセット                                                                                                                                    
        // adapter.notifyDataSetChanged();とか                                                                                                                                                                 
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_my, container, false);

        // ListViewセット                                                                                                                                                                                          
        ListView listView = (ListView)view.findViewById(R.id.list_view);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                ・・・
            });

        return view;
    }

    public class UserData {
        ・・・
    }

    public class UserDataAdapter extends ArrayAdapter<UserData> {
        ・・・
    }
}

以上です

【android】FragmentのListViewを選択で画面遷移する方法

はじめに

Android開発ではFragmentを使った画面の開発が常套手段ぽい。

なので今回はFragment上の画面にListViewを表示して、セルをタップしたら詳細画面用のFragmentを表示。詳細画面へ遷移後に戻るボタンでListViewの画面に戻る画面を作ってみた。

ファイル構成とそれぞれやることは以下

・MainActivity.java、activity_main.xml
ここのレイアウトに一覧画面ではfragment_mainを詳細画面ではfragment_detailを表示する。
起動時はMainFragmentをセットする。

・MainFragment.java、fragment_main.xml
ListViewにデータの表示とセルを選択されたときにDetailFragmentを呼ぶ。

・DetailFragment.java、fragment_detail.xml
詳細画面用

実装

メインアクティブティ

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:id="@+id/activity_main"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context="xxx.samplefragment.MainActivity">
  <!-- ここにフラグメントをセット -->
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/main_fragment"></LinearLayout>

</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ListView表示用のフラグメントをセット
        MainFragment mainFragment = new MainFragment();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.main_fragment,mainFragment);
        transaction.commit();
    }
}
ListView表示用フラグメント

fragment_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="xxx.samplefragment.MainFragment">
  <ListView
      android:id="@+id/list_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"></ListView>
</FrameLayout>

MainFragment.java

public class MainFragment extends Fragment {
    public MainFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main, container, false);
        return view;
    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // ListViewに表示するデータ
        final ArrayList<String> items = new ArrayList<>();
        items.add("データ1");
        items.add("データ2");
        items.add("データ3");

        // ListViewをセット
        final ArrayAdapter adapter = new ArrayAdapter(this.getContext(), android.R.layout.simple_list_item_1, items);
        ListView listView = (ListView) view.findViewById(R.id.list_view);
        listView.setAdapter(adapter);
        // セルを選択されたら詳細画面フラグメント呼び出す
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                    // 詳細画面へ値を渡す
                    DetailFragment fragment = new DetailFragment();
                    Bundle bundle = new Bundle();
                    bundle.putInt("selected",position);
                    fragment.setArguments(bundle);
                    // 詳細画面を呼び出す
                    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
                    FragmentTransaction transaction = fragmentManager.beginTransaction();
                    transaction.replace(R.id.main_fragment, fragment);
                    // 戻るボタンで戻ってこれるように
                    transaction.addToBackStack(null);
                    transaction.commit();
                }
            });
    }
}
詳細画面用フラグメント

fragment_detail.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="xxx.samplefragment.DetailFragment">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>

DetailFragment.java

public class DetailFragment extends Fragment {
    public DetailFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Bundle args = getArguments();
        int selected = args.getInt("selected");

        View view = inflater.inflate(R.layout.fragment_detail, container, false);
        TextView textView = (TextView)view.findViewById(R.id.textView);
        textView.setText(String.valueOf(selected) + "番目が選択されました");
        return view;
    }
}

コードそのままだけでこんな感じでやりたいことができました。
以上です

【android】android.support.designライブラリを追加して使用する手順

サポートライブラリ追加手順です

f:id:yoppy0066:20170116233958p:plain
・[File]>[Project Structure]を開く


f:id:yoppy0066:20170116234042p:plain
・[app]を選択
・ [Dependencies]を選択


f:id:yoppy0066:20170116234121p:plain
・ [+]>[1 Library dependency]を選択


f:id:yoppy0066:20170116234132p:plain
・ 検索バーに「design」と入力してEnter
・ [com.android.support:design(com.android.support:design:25.1.0)]を選択して[OK]をクリック

以上です

【swift】UILabelの高さを計算して動的に変更(調整)する

よくやってるつもりだったけど意外と整理できていなかったので整理

var myLabel = UILabel();

// 最大行数を指定(0は無制限)
myLabel.numberOfLines = 0;

// 表示するテキストをセット
myLabel.text = "テキスト・・・";

// セットした文字からUILabelの幅と高さを算出
var rect: CGSize = myLabel.sizeThatFits(CGSize(width: frame.width, height: CGFloat.greatestFiniteMagnitude))

// 算出された幅と高さをセット
myLabel.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)

以上です