Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

RootViewController

WindowのRootViewControllerをすげ替えるとUIViewControllerを変えられるがWindowにくっつけていたViewも消える。。orz。

以下実験コード

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewDidAppear(_ animated: Bool) {
        let v = UIView(frame: self.view.bounds)
        v.backgroundColor = UIColor.blue
        let gesture = UITapGestureRecognizer(target: self, action: #selector(buttonPushed(sender:)))
        v.addGestureRecognizer(gesture)
        self.view.window!.addSubview(v)
    }
    
    @IBAction func buttonPushed(sender:Any?) {
        print("buttonPushed")
        let story = UIStoryboard(name: "Main", bundle: nil)
        let v2 = story.instantiateViewController(withIdentifier: "v2")
        self.view.window?.rootViewController = v2
    }
    


}

class名を抜き出す

色々他のサイトを検索しつつやってみたができた感じがする。

#coding:utf-8
import os.path # ファイル操作
import shutil # 再帰的削除
import glob # ファイル一括
import re # 正規表現
# http://quzee.hatenablog.com/entry/2015/08/15/151210

# ファイルを開く
def show(file):
        with open( file, "r") as f:
            for row in f:
                print(row.strip())

# パス内のファイルとディレクトリを返す
def getList(path):
    files = os.listdir(path)
    return files

# "*.*"等で検索
def getListGlob(gobpath):
    files = glob.glob(gobpath)
    return files

def isFile(path):
    return os.path.isfile(path)

# http://qiita.com/suin/items/cdef17e447ceeff6e79d
def find_all_files(directory):
    for root, dirs, files in os.walk(directory):
        yield root
        for file in files:
            yield os.path.join(root, file)

# フォルダ内のリストを取得
# http://qiita.com/wanwanland/items/ce272419dde2f95cdabc
for f in find_all_files('./'):
    if isFile(f):
        if re.match(r".*\.swift",os.path.basename(f)):
            # print(f)
            with open( f, "r") as of:
                lines = of.readlines()

            for line in lines:
                #print(line)
                matchOb = re.search(r"class .*", line)
                if matchOb:
                    className = matchOb.group()
                    print(className)




基本

パイプライン

コマンド1|コマンド2

コマンドの標準出力がコマンドの標準入力になる。

コマンドリスト

左から

コマンド1; コマンド2

前が成功(終了コード0)で後も実行

コマンド1 && コマンド2


前が成功以外(終了コード0以外)で後も実行

コマンド1 || コマンド2

コマンド置換

$()は()内のコマンド実行結果におきかえで実行される。

touch $(date + %F)

文字列のブレース展開

echo {A,B,C}
echo {1..5}

bashのブレース展開についてまとめ - Qiita

ループ

for i in 1 2 3
do
 echo "$i"
done 
x=10
while [ $x -gt 0 ]
do
  echo "$x"
  x=$(expr $x - 1) 
done
  • gtは>の意味、条件式を[]で囲った。exprは四則演算、$()は中のコマンドを実行した結果をxにいれるため。

bash/shで計算(四則演算)をする方法。 - それマグで!

chmod

実行権限等を与える。

chmod a+x hoge.sh

aはすべて、xは実行権限、+は与える。

1. x実行 r読み込み w書き込み
2. aはすべての人, oは所有者, gはグループ, oはその他ユーザ

Linuxコマンド集 - 【 chmod 】 ファイルやディレクトリのアクセス権を変更する:ITpro

2分木

2分木らしきものを作った。あっているかはさておき。

import Foundation


class N  {
    static var count:Int = 0
    var identifier:Int = 0
    var v:Int = 0
    var small:N? = nil
    var big:N? = nil
    
    func add(_ n:N) {
        if self.v > n.v {
            if let small = self.small {
                small.add(n)
            } else {
                self.small = n
            }
        } else {
            if let big = self.big {
                big.add(n)
            } else {
                self.big = n
            }
        }
    }
    
    init(_ v:Int) {
        self.identifier = N.count
        N.count = N.count + 1
        self.v = v
    }
    
    func selfdesc() -> String {
        return "\(self.identifier):\(self.v)"
    }
    
    func desc() -> String {
        let small = self.small?.desc() ?? ""
        let big = self.big?.desc() ?? ""
        
        return ("(\(self.v) \(small) \(big))")
    }
    
    func idesc() -> String {
        let small = self.small?.idesc() ?? ""
        let big = self.big?.idesc() ?? ""
        
        return ("(\(self.selfdesc()) \(small) \(big))")
    }
}

自動テスト

エレメントがあるかを待つ。作りかけ。これが使えるかは謎。

    func waitForElementAppear(element: XCUIElement, time:TimeInterval = 5, file: String = #file, line:UInt = #line) -> Bool {
        
        //let exp = XCTKVOExpectation(keyPath: "exsits", object: element)
        //        let result = XCTWaiter().wait(for: [exp], timeout: time)
        
        let predicate = NSPredicate {
            if let e = $0.0 as? XCUIElement {
                return e.exists
            } else {
                return false
            }
        }
        
        let exp = XCTNSPredicateExpectation(predicate: predicate, object: element)
        
        let result = XCTWaiter.wait(for: [exp], timeout: time)
        
        return result == .completed
    }

テスト環境の追加とprovisioning

テスト環境を後から追加しようとしてprovisioningでエラーになっていた。
Build SettingのProvisioning(Deprecated)をautomaticにし、generalタブでprovisioningをautomaticにチェックを入れると動いた。

参考
qiita.com

migration

テーブルを作る

./bin/cake bake migration CreateProducts name:string description:text created modified

Migrations - 3.x

マイグレーション実行

./bin/cake migrations migrate

これでproductsテーブルができた。

現在のスナップショット

bin/cake bake migration_snapshot Initial

マイグレーション

  1. CreateHoges Hogeテーブル作成
  2. DropHoges Hogeテーブル削除
  3. AddFugaToHoges fuga:text Hogeテーブルにfugaカラム追加
  4. RemoveFugaFrom fuga Hogeテーブルからfugaカラム削除
  5. Alter 調査中

Seed

bin/cake bake seed Hoges

Seedを設定

  public function run()
    {
        // $data = [];
        $data = [
          [
            'description'    => 'foo',
            'created' => date('Y-m-d H:i:s'),
          ],[
            'description'    => 'bar',
            'created' => date('Y-m-d H:i:s'),
          ]
        ];

        $table = $this->table('hoges');
        $table->insert($data)->save();
    }

実行

bin/cake migrations seed

Sqlite3メモ

セレクト

sqlite> select description, modified, created  from hoges;

bake

次のものがbakeできるようだ。

$ ./bin/cake bake

- all
- behavior
- cell
- component
- controller
- fixture
- form
- helper
- mailer
- middleware
- migration
- migration_diff
- migration_snapshot
- model
- plugin
- seed
- shell
- shell_helper
- task
- template
- test

helpをみてみる

$ ./bin/cake bake --help
The Bake script generates controllers, models and template files for
your application. If run with no command line arguments, Bake guides the
user through the class creation process. You can customize the
generation process by telling Bake where different parts of your
application are using command line arguments.

Usage:
cake bake [subcommand] [options]

Subcommands:

all                 Bake a complete MVC skeleton.
behavior            Bake a behavior class file.
cell                Bake a cell class file.
component           Bake a component class file.
controller          Bake a controller skeleton.
fixture             Generate fixtures for use with the test suite. You
                    can use `bake fixture all` to bake all fixtures.
form                Bake a form class file.
helper              Bake a helper class file.
mailer              Bake a mailer class file.
middleware          Bake a middleware class file.
migration           Bake migration class.
migration_diff      Bake migration class.
migration_snapshot  Bake migration snapshot class.
model               Bake table and entity classes.
plugin              Create the directory structure, AppController class
                    and testing setup for a new plugin. Can create
                    plugins in any of your bootstrapped plugin paths.
seed                Bake seed class.
shell               Bake a shell class file.
shell_helper        Bake a shell_helper class file.
task                Bake a task class file.
template            Bake views for a controller, using built-in or
                    custom templates.
test                Bake test case skeletons for classes.

To see help on a subcommand use `cake bake [subcommand] --help`

Options:

--connection, -c   Database connection to use in conjunction with `bake
                   all`. (default: default)
--everything       Bake a complete MVC skeleton, using all the available
                   tables. Usage: "bake all --everything"
--force, -f        Force overwriting existing files without prompting.
--help, -h         Display this help.
--plugin, -p       Plugin to bake into.
--prefix           Prefix to bake controllers and templates into.
--quiet, -q        Enable quiet output.
--tablePrefix      Table prefix to be used in models.
--theme, -t        The theme to use when baking code. (choices:
                   Bake|Migrations)
--verbose, -v      Enable verbose output.

基本的メモ

php -a

で対話モード

phpinfo();

phpの情報が見れる。php.iniの場所もわかる。

もしくはコマンド実行

php -r "info();"

でも良い。

というか

 php -i 

で良い。

php -i | grep php.ini

というか

php --ini

で良いようだ。

今回はphp_intlのextensionを使うために調べた。国際化のための拡張モジュールでCakePHP3のインストールのために。
macapatchを再起動させてphp.iniを反映させる。

sudo apachectl restart

モジュール

モジュールは

php -m

でロードされているものが何かわかる。

で、結局intlをダウンロードする仕方がわからなかったのでphp7にした。

brew install homebrew/php/php70
brew install php70-intl

ファイル操作

ファイル名変更に一時間以上費やしている..
使い方を調べるためにラッパークラスを書いてみた。直接使えば良いのであまり意味はない。

#coding:utf-8
import os.path # ファイル操作
import shutil # 再帰的削除
import glob # ファイル一括
import re # 正規表現

class FileUtil:
    def __init__(self, file):
        self.file = file

    def show(self):
        with open( self.file, "r") as f:
            for row in f:
                print(row.strip())

    # ファイルが存在しない場合は新規作成
    # 追加しない
    def write(self, text):
        with open( self.file, "w") as f:
            f.write(text)

    def isExist(self):
        return os.path.exists(self.file)

    def removeFile(self):
        os.remove(self.file)

    def deleteDirectory(self):
        shutil.rmtree(self.file)

    def echo(self):
        print(self.file)

    def setFileName(self, file):
        self.file = file

    def isFile(self):
        return os.path.isfile(self.file)

    def isDir(self):
        return os.path.isdir(self.file)

    def rename(self,name):
        os.rename(self.file, name)

# ref http://qiita.com/supersaiakujin/items/12451cd2b8315fe7d054

def sampleFileUtil():
    u = FileUtil("hoge.txt")
    u.show()

# fileRename(r"hoge", r"Fuga")
def fileRename(before, after):
    flist = glob.glob("*.*")
    cN = lambda target : changeName(target, before, after)
    l = list(map(cN, flist))
    for before, after in zip(flist, l):
        os.rename(before, after)
        print(before + " -> " + after)

def changeName(target, before, after):
    return re.sub(before,after, target)