Rodhos Soft

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

カスタムメニュー

つかったことがないが。。

    override func viewDidLoad() {
        super.viewDidLoad()

        UIMenuController.shared.arrowDirection = .right;
        UIMenuController.shared.menuItems = [UIMenuItem.init(title: "a", action: #selector(hello))]
        let r = CGRect(x: 0, y: 0, width: 40, height: 40)
        UIMenuController.shared.setTargetRect(r, in: self.view)
        
        UIMenuController.shared.setMenuVisible(true, animated: true);
       
        UIMenuController.shared.update()
    }
    
    func hello() {
        print("hello")
    }

    
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if (action == #selector(hello)) {
            return true
        }
        return false
    }

カスタムビューのXCode表示

@IBDesignable class MyView: UIView {

    @IBInspectable var cornerRadius : CGFloat = 0.0;
    
    
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
        self.layer.cornerRadius = cornerRadius
        if cornerRadius > 0 {
            self.clipsToBounds = true;
        }
    }
    

}

木構造的なもの

LISPのようなものを作ろうとしたら単に文字列の結合を木構造でやるということになっていた。でもクラスについてだいぶ勉強になった。

//
//  RDLisp.hpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#ifndef RDLisp_hpp
#define RDLisp_hpp

#include <iostream>
#include <stdio.h>

namespace RDLisp {
    
    template<class T>
    using Share = std::shared_ptr<T>;

    
    class Printable {
    public:
        virtual std::string description() = 0;
    };
    
    
    class S : public Printable{
    public:
    };
    
    class Value;
    
    class Pair : public S {
    public:
        Share<S> car;
        Share<S> cdr;
        Pair(Share<S> car, Share<S> cdr) {
            this->car = car;
            this->cdr = cdr;
        }
        
        std::string description();
        bool isFunc();
        bool isValue();
    };
    
    
    class Nil : public S {
    public:
        Nil();
        std::string description();
    };
    
    class Symbol;
    class Value;
    
    class Atom  : public S {
    public:
        std::string value;
        Atom(std::string value) {
            this->value = value;
        };
        std::string description();
    };
    
    
    class Value : public Atom {
    public:
        Value(std::string value) : Atom(value) {
            
        };
    };
    
    /// symbol is function
    class Symbol : public Atom {
    public:
        Symbol(std::string value) : Atom(value) {
            
        };
    };
    

    Share<S> eval(Share<S> s);
    Share<S> apply(Share<Symbol> sy, Share<S> target);
}



#endif /* RDLisp_hpp */
//
//  RDLisp.cpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#include "RDLisp.hpp"

#include <vector>
#include <string>

namespace RDLisp {
    
    template <class T>
    Share<T> scast(Share <S> s) {
        return std::dynamic_pointer_cast<T>(s);
    }
    
    Share<Value> add(Share<S> target, int n) {
        std::cout <<std::string(n, ' ') << "+"<< "\n";

        if (auto v = scast<Value>(target)) {
            std::cout << std::string(n, ' ')<< v->description() << "\n";
            return v;
        }
        
        if (auto p = scast<Pair>(target)) {
            
            if (auto s = scast<Symbol>(p->car)) {
                auto cdr_after = apply(s, p->cdr);
                if (auto v = scast<Value>(cdr_after)) {
                    return v;

                } else {
                    return nullptr;
                }
            }
            
            if (auto f = scast<Value>(p->car)) {
                auto l = add(p->cdr, n+1);
                if (f&&l) {
                    auto v = std::make_shared<Value>(f->value + l->value);
                    
                    std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                    return v;
                } else {
                    return nullptr;
                }
            }
            
            if (auto l = scast<Value>(p->cdr)) {
                auto f = add(p->car, n+1);
                if (f&&l) {
                    auto v = std::make_shared<Value>(f->value + l->value);
                    
                    std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                    return v;
                } else {
                    return nullptr;
                }
            }
            
            
            auto f = add(p->car, n+1);
            auto l = add(p->cdr, n+1);
            if (f&&l) {
                auto v = std::make_shared<Value>(f->value + l->value);
                
                std::cout <<std::string(n, ' ')<< "["<< v->description() << "]"<< "\n";
                return v;
            } else {
                return nullptr;
            }
        }
        
        std::cout <<std::string(n, ' ')<< "nullptr"<< "\n";
        return nullptr;
    }
    

    
    Share<S> eval(Share<S> exp) {
        auto pair = scast<Pair>(exp);
        if (pair) {
            if (pair->isFunc()) {
                auto sy = std::dynamic_pointer_cast<Symbol>(pair->car);
//                auto crd_after = eval(pair->cdr);
//                std::cout << "crd_after" + crd_after->description() + "\n";
                return apply(sy, pair->cdr);
//                return apply(sy, crd_after);

            }
        }
        
        return exp;
    }
    
    Share<S> apply(Share<Symbol> sy, Share<S> target) {
        
        if (sy->value == "+") {
            if (auto v = scast<Value>(target)) {
                return target;
            }
            
            if (auto p = scast<Pair>(target)) {
                auto exp = add(target, 0);
                if (exp) {
                    return exp;
                }
            }
            
        }
        
        return std::make_shared<Pair>(sy,target);
    }

    
    bool Pair::isFunc() {
        auto sy = std::dynamic_pointer_cast<Symbol>(this->car);
        if (sy) {
            return true;
        }
        return false;
    }
    


    
    std::string Pair::description() {
        return "(" + this->car->description() + " " + this->cdr->description() + ")";  
    }
    
    std::string Atom::description() {
        return this->value;
    }

    std::string Nil::description() {
        return "";
    }

    

}

実行は次のようにする。面倒。

//
//  main.cpp
//  RDLisp
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#include <iostream>
#include "RDLisp.hpp"

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    
    using namespace RDLisp;
    using namespace std;
    
    auto a1 = make_shared<Value>("a1");
    auto a2 = make_shared<Value>("a2");
    auto pair_a = make_shared<Pair>(a1,a2);
    auto b = make_shared<Value>("b");
    auto c = make_shared<Value>("c");
    auto d = make_shared<Value>("d");
    auto add = make_shared<Symbol>("+");
    auto add2 = make_shared<Symbol>("+");
    auto pair_ab = make_shared<Pair>(pair_a,b);
    auto pair_cd = make_shared<Pair>(c,d);
    auto pair = make_shared<Pair>(add, pair_ab);
    auto pair2 = make_shared<Pair>(add, pair_cd);
    auto pair3 = make_shared<Pair>(pair, pair2);
    auto pair4 = make_shared<Pair>(add2, pair3);
    
    std::cout << pair4->description() << "\n";
    
    auto res = eval(pair4);
    
    std::cout << res->description() << "\n";

    
    return 0;
}

結果は

Hello, World!
(+ ((+ ((a1 a2) b)) (+ (c d))))
+
 +
+
 +
  +
  a2
 [a1a2]
[a1a2b]
 +
+
 +
 d
[cd]
[a1a2bcd]
a1a2bcd
Program ended with exit code: 0

練習 文字列等

文字列等の練習にコマンドと引数の対をとるコードを書いてみた。引数には対自体を入れることができるとする。

結果はこんな感じになる。

>+ * 100
(+ (* ( 100)))
#ifndef RDCalc_hpp
#define RDCalc_hpp

#include <stdio.h>
#include "RDConfig.hpp"

class Command {
public:
    Command() = default;
    ~Command() = default;
    
    std::string name;
    std::string description();
};


class Value;

class Term {
public:
    Term() = default;
    ~Term() = default;
    std::shared_ptr<Command> command;
    std::shared_ptr<Term> value;
    std::string name;
    std::string description();
};

class Value : public Term {
public:
    Value();
    ~Value() = default;
};




class RDCalc {
public:
    RDCalc();
    ~RDCalc();
    void start();
    std::string calc(std::string);
    std::shared_ptr<Term> state;
private:
    std::shared_ptr<Term> getTerm(std::vector<std::string>);
    
};

#endif /* RDCalc_hpp */
//
//  RDCalc.cpp
//  RDCalcSystem
//
//  Created by KatagiriSo on 2017/09/26.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

#include <sstream>
#include <iostream>
#include "RDCalc.hpp"
#include<string>
#include<vector>

RDCalc::RDCalc() {
    
}

RDCalc::~RDCalc() {
    std::cout << "RDCalc dec.\n";

}

void RDCalc::start() {
    std::string input;

    while(true) {
        std::cout << ">";
        
        std::string str;
        std::vector<std::string> v;

        std::getline(std::cin, str);
        
        auto output = RDCalc::calc(str);
        std::cout << output << std::endl;
    }
}

std::vector<std::string> splitString(std::string input) {
    std::stringstream ss;
    ss << input;
    
    std::vector<std::string> v;
    
    std::string com;
    while(ss >> com) {
        v.push_back(com);
    }
    return v;
}




std::string RDCalc::calc(std::string input) {
    
    std::vector<std::string> v = splitString(input);
    
    this->state = getTerm(v);
    
    if (this->state == nullptr) {
        return "?\n";
    }
    
    return this->state->description();
}

std::shared_ptr<Term> RDCalc::getTerm(std::vector<std::string> v) {
    
    auto term = std::make_shared<Term>();
    auto command = std::make_shared<Command>();
    
//    if (m=="+") {
//
    auto m = v.front();
    v.erase(v.begin());
    if (v.empty()) {
        term->command = command;
        term->command->name = "";
        auto value = std::make_shared<Value>();
        value->name = m;
        term->value = value;
    } else {
        command->name = m;
        
        term->command = command;
        term->value = getTerm(v);
    }
    
    
    return term;
}


std::string Term::description() {
    if (this->value == nullptr) {
        return this->name;
    }
    return "(" + this->command->description() + " " + this->value->description() + ")";
}

std::string Command::description() {
    return this->name;
}

Value::Value() {
    command = std::make_shared<Command>();
    command->name = "";
}

たまに使うショートカット

⌘ {  でタブ移動
⌘デリート でその文頭からカーソルまで削除
⌘→ 行末へ移動
エスケープ 補完リスト表示
⌘T 新しいタブ作成



キー

⌘ コマンド

⌥ オプション

⇧ シフト

⌃ コントロール

エスケープは○に左上に棒が入っているマーク

OS X Yosemite: メニューに表示される記号

コマンドライン

参考
yamaimo.hatenablog.jp


コンパイルする場合はswiftcを使う。

$ swiftc -help
OVERVIEW: Swift compiler

USAGE: swiftc [options] <inputs>

MODES:
  -dump-ast        Parse and type-check input file(s) and dump AST(s)
  -dump-parse      Parse input file(s) and dump AST(s)
  -dump-scope-maps <expanded-or-list-of-line:column>
                   Parse and type-check input file(s) and dump the scope map(s)
  -dump-type-refinement-contexts
                   Type-check input file(s) and dump type refinement contexts(s)
  -emit-assembly   Emit assembly file(s) (-S)
  -emit-bc         Emit LLVM BC file(s)
  -emit-executable Emit a linked executable
  -emit-ir         Emit LLVM IR file(s)
  -emit-library    Emit a linked library
  -emit-object     Emit object file(s) (-c)
  -emit-sibgen     Emit serialized AST + raw SIL file(s)
  -emit-sib        Emit serialized AST + canonical SIL file(s)
  -emit-silgen     Emit raw SIL file(s)
  -emit-sil        Emit canonical SIL file(s)
  -parse           Parse input file(s)
  -print-ast       Parse and type-check input file(s) and pretty print AST(s)
  -typecheck       Parse and type-check input file(s)

OPTIONS:
  -application-extension  Restrict code to those available for App Extensions
  -assert-config <value>  Specify the assert_configuration replacement. Possible values are Debug, Release, Unchecked, DisableReplacement.
  -continue-building-after-errors
                          Continue building, even after errors are encountered
  -driver-time-compilation
                          Prints the total time it took to execute all compilation tasks
  -D <value>              Marks a conditional compilation flag as true
  -embed-bitcode-marker   Embed placeholder LLVM IR data as a marker
  -embed-bitcode          Embed LLVM IR bitcode as data
  -emit-dependencies      Emit basic Make-compatible dependencies files
  -emit-module-path <path>
                          Emit an importable module to <path>
  -emit-module            Emit an importable module
  -emit-objc-header-path <path>
                          Emit an Objective-C header file to <path>
  -emit-objc-header       Emit an Objective-C header file
  -fixit-all              Apply all fixits from diagnostics without any filtering
  -fixit-code             Get compiler fixits as code edits
  -framework <value>      Specifies a framework which should be linked against
  -F <value>              Add directory to framework search path
  -gdwarf-types           Emit full DWARF type info.
  -gline-tables-only      Emit minimal debug info for backtraces only
  -gnone                  Don't emit debug info
  -g                      Emit debug info. This is the preferred setting for debugging with LLDB.
  -help                   Display available options
  -import-underlying-module
                          Implicitly imports the Objective-C half of a module
  -index-store-path <path>
                          Store indexing data to <path>
  -I <value>              Add directory to the import search path
  -j <n>                  Number of commands to execute in parallel
  -L <value>              Add directory to library link search path
  -l<value>               Specifies a library which should be linked against
  -module-cache-path <value>
                          Specifies the Clang module cache path
  -module-link-name <value>
                          Library to link against when using this module
  -module-name <value>    Name of the module to build
  -nostdimport            Don't search the standard library import path for modules
  -num-threads <n>        Enable multi-threading and specify number of threads
  -Onone                  Compile without any optimization
  -Ounchecked             Compile with optimizations and remove runtime safety checks
  -output-file-map <path> A file which specifies the location of outputs
  -O                      Compile with optimizations
  -o <file>               Write output to <file>
  -parse-as-library       Parse the input file(s) as libraries, not scripts
  -parse-sil              Parse the input file as SIL code, not Swift source
  -parseable-output       Emit textual output in a parseable format
  -profile-coverage-mapping
                          Generate coverage data for use with profiled execution counts
  -profile-generate       Generate instrumented code to collect execution counts
  -sanitize-coverage=<type>
                          Specify the type of coverage instrumentation for Sanitizers and additional options separated by commas
  -sanitize=<check>       Turn on runtime checks for erroneous behavior.
  -save-temps             Save intermediate compilation results
  -sdk <sdk>              Compile against <sdk>
  -serialize-diagnostics  Serialize diagnostics in a binary format
  -static-executable      Statically link the executable
  -static-stdlib          Statically link the Swift standard library
  -suppress-warnings      Suppress all warnings
  -swift-version <vers>   Interpret input according to a specific Swift language version number
  -target-cpu <value>     Generate code for a particular CPU variant
  -target <value>         Generate code for the given target
  -tools-directory <directory>
                          Look for external executables (ld, clang, binutils) in <directory>
  -use-ld=<value>         Specifies the linker to be used
  -version                Print version information and exit
  -v                      Show commands to run and use verbose output
  -warnings-as-errors     Treat warnings as errors
  -whole-module-optimization
                          Optimize input files together instead of individually
  -Xcc <arg>              Pass <arg> to the C/C++/Objective-C compiler
  -Xlinker <value>        Specifies an option which should be passed to the linker

そしてswiftというコマンドもある。

$ swift -h
OVERVIEW: Swift compiler

USAGE: swift [options] <inputs>

OPTIONS:
  -assert-config <value> Specify the assert_configuration replacement. Possible values are Debug, Release, Unchecked, DisableReplacement.
  -continue-building-after-errors
                         Continue building, even after errors are encountered
  -D <value>             Marks a conditional compilation flag as true
  -framework <value>     Specifies a framework which should be linked against
  -F <value>             Add directory to framework search path
  -gdwarf-types          Emit full DWARF type info.
  -gline-tables-only     Emit minimal debug info for backtraces only
  -gnone                 Don't emit debug info
  -g                     Emit debug info. This is the preferred setting for debugging with LLDB.
  -help                  Display available options
  -index-store-path <path>
                         Store indexing data to <path>
  -I <value>             Add directory to the import search path
  -j <n>                 Number of commands to execute in parallel
  -L <value>             Add directory to library link search path
  -l<value>              Specifies a library which should be linked against
  -module-cache-path <value>
                         Specifies the Clang module cache path
  -module-link-name <value>
                         Library to link against when using this module
  -module-name <value>   Name of the module to build
  -nostdimport           Don't search the standard library import path for modules
  -num-threads <n>       Enable multi-threading and specify number of threads
  -Onone                 Compile without any optimization
  -Ounchecked            Compile with optimizations and remove runtime safety checks
  -O                     Compile with optimizations
  -sdk <sdk>             Compile against <sdk>
  -static-executable     Statically link the executable
  -static-stdlib         Statically link the Swift standard library
  -suppress-warnings     Suppress all warnings
  -swift-version <vers>  Interpret input according to a specific Swift language version number
  -target-cpu <value>    Generate code for a particular CPU variant
  -target <value>        Generate code for the given target
  -use-ld=<value>        Specifies the linker to be used
  -version               Print version information and exit
  -v                     Show commands to run and use verbose output
  -warnings-as-errors    Treat warnings as errors
  -Xcc <arg>             Pass <arg> to the C/C++/Objective-C compiler
  -Xlinker <value>       Specifies an option which should be passed to the linker

Swiftは対話モードで実行できる。

$ swift
Welcome to Apple Swift version 3.1 (swiftlang-802.0.53 clang-802.0.42). Type :help for assistance.
  1> 3+2
$R0: Int = 5
  2> class A { 
  3.     var hoge:Int? = nil 
  4.     func hello() { 
  5.         print("hello \(hoge)") 
  6.     } 
  7. } 
  8> let a = A()
a: A = {
  hoge = nil
}
  9> a.hoge = 100
 10> a.hello()
hello Optional(100)
 11>  

クラスとtrait

traitは入れ子にできる。

<?php

class BaseClass {

}

trait Helloable {
  public function hello() {
    echo "hello\n";
  }
}

class MyClass extends BaseClass {

  use Helloable;

  public $hoge = "ABC\n";

  public function display() {
    echo $this->hoge;
  }
}

$ins = new MyClass();
$ins->display();
$ins->hello();

?>

文字列ストリーム風

以下でStream(Array(src.characters))としてやれば文字列stream風になる。

    class Stream<T> {
        let m_value:[T]
        var count = 0
        init(_ v:[T]) {
            m_value = v
        }
        
        func get()->T? {
            if count < m_value.count {
                let ret = m_value[count]
                count = count + 1
                print("\(ret)")
                return ret
                
            } else {
                return nil
            }
        }
        
        func unget() {
            count = count - 1
            print("unget")
            if count < 0 {
                count = count + 1
            }
        }
    }

GCDの例

SwiftでGCDのgroup等の使い方のサンプルを書いてみた。

//
//  ViewController.swift
//  GCDSample
//
//  Created by KatagiriSo on 2017/09/19.
//  Copyright © 2017年 RodhosSoft. All rights reserved.
//

import UIKit

class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
    
    
    struct Menu {
        let name:String
    }
    
    let menu:[Menu] = [Menu(name: NSStringFromSelector(#selector(AsyncBarrier))),
                       Menu(name: NSStringFromSelector(#selector(GroupWait))),
                       Menu(name: NSStringFromSelector(#selector(GroupNotify))),
                       Menu(name: NSStringFromSelector(#selector(GroupEnterLeave))),
                       Menu(name: NSStringFromSelector(#selector(SemaphoExample)))

        
                       ]
    
    func makeEqualConstraint(item:Any, toItem:Any, attribute:NSLayoutAttribute) ->  NSLayoutConstraint{
        return NSLayoutConstraint(item: item, attribute: attribute, relatedBy: .equal, toItem: toItem, attribute: attribute, multiplier: 1.0, constant: 0)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let tableView:UITableView = UITableView(frame: self.view.bounds)
        tableView.delegate = self
        tableView.dataSource = self
        
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")

        
        self.view.addSubview(tableView)
        
        
        let l = makeEqualConstraint(item: tableView, toItem: self.view, attribute: .left)
        let r = makeEqualConstraint(item: tableView, toItem: self.view, attribute: .right)
        let t = makeEqualConstraint(item: tableView, toItem: self.view, attribute: .top)
        let b = makeEqualConstraint(item: tableView, toItem: self.view, attribute: .bottom)
        
        l.isActive = true
        r.isActive = true
        t.isActive = true
        b.isActive = true

    }
    
    

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return menu.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = menu[indexPath.row].name
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selector = NSSelectorFromString(menu[indexPath.row].name)
        self.perform(selector)
    }
    
    func AsyncBarrier() {
        print("\(#function)")
        
        let queue = DispatchQueue(label: "asyncBarrierTest")
        [1,2,3,4,5,6,7,8,9,10].forEach { n in
            queue.async {
                print("done \(n)")
            }
        }
        
        queue.async(flags:.barrier) {
            print("all done")
        }
        
        print("\(#function) end")
    }
    
    func GroupWait() {
        print("\(#function)")
        
        let queue = DispatchQueue(label: "groupWaitTest")
        let group = DispatchGroup()
        
        for n in 1...100 {
            queue.async(group: group) {
                print("done \(n)")
            }
        }
        
        print("group.wait")
        let _ = group.wait(timeout: DispatchTime.distantFuture)
        
        
        print("\(#function) end")
    }
    
    func GroupNotify() {
        print("\(#function)")
        
        let queue = DispatchQueue(label: "GroupNotify")
        let group = DispatchGroup()
        
        for n in 1...100 {
            queue.async(group: group) {
                print("done \(n)")
            }
        }
        
        group.notify(queue: queue) {
            print("done")
        }
        
        print("\(#function) end")
    }
    
    func GroupEnterLeave() {
        print("\(#function)")
        
        let queue = DispatchQueue(label: "GroupNotify")
        let group = DispatchGroup()
        
        for n in 1...100 {
            group.enter()
            queue.async {
                print("done \(n)")
                group.leave()
            }
        }
        
        group.notify(queue: queue) {
            print("done")
        }
        
        print("\(#function) end")
    }
    
    func SemaphoExample() {
        
        print("\(#function)")
        
        let semapho = DispatchSemaphore(value: 0)
        
//        semapho.wait()

        DispatchQueue.global().async {
            for n in 1...100 {
                print("count \(n)")
            }
            
            semapho.signal()
        }
        
        
        print("wait")
        semapho.wait()
        
        
        print("\(#function) end")
    }

    


}