Cocoa練習帳 -4ページ目

[Swifty]Struct化

関連情報ではClassだと値を変更したら、他で参照しているところにも影響を与えるのでStructを勧めていたが、Model(Dataコントローラ)の実装次第だと思っている。ただ、これは次の関数型プログラミングの導入のためだと思うので、素直に従う。

C++のことを考えると誤解が発生しそうなので、利用するのが躊躇してしまう、リファレンス型と値というのがSwiftにあって、Structは値型のため、=で代入するとコピーとなる。ただ、自分がここで混乱してしまったが、冷静に考えると、SwiftのオブジェクトはObjective-Cのid型で、ARCでメモリ管理されているはずで、Structでは=演算子がコピーするようになっているということだろう。

値型でコピーとなるとコストの問題が気になるが、Swiftでは配列はCopy-On-Writeという考えで実装されていて、=演算子で代入する際は、idのコピーで、値の変更が派生する際に、中身のコピーが発生するので、気にする必要はないようだ。

ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Hand - GitHub
関連情報 文化を調和させる
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[Swifty]アクセス制御

publicとinternal、privateの事。

Swiftを紹介する際、ガードのため、安全のため、という説明をされる事が多い。
あえて物議を醸し出すが、危険な経験があるか。そして、スマートフォンの場合、クラスを作るのも、それを使うのも自分という場合があるが、本当に安全のため?

著者は、privateは、そのクラスのインタフェースを確認する際、無視していいよ程度の意味だと思っている。
なので、Privateとpublicの順で記述している。

class Demo {
    public var name;
    public func play() {
        playGame();
    }
    private var address;
    private func playGame() {
    }
}

そう考えると、Objective-Cはよかったじゃん。

@interface Document : NSObject
@property (strong, nonatomic) NSString *version;
+ (Document *)sharedDocument;
- (void)load;
- (void)save;
@end

@interface Document ()
- (void)_clearDefaults;
- (void)_updateDefaults;
- (void)_loadDefaults;
- (NSString*)_modelDir;
- (NSString*)_modelPath;
@end
 
@implementation Document
@synthesize version = _version;
 
+ (Document *)sharedDocument;
{
    static Document *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[Document alloc] init];
    });
    return _sharedInstance;
}
 
- (id)init
{
    self = [super init];
    if (self) {
        _version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    }
    return self;
}
 
- (void)dealloc
{
    self.version = nil;
}
 
- (void)load
{
    [self _loadDefaults];
    
    NSString    *modelPath = [self _modelPath];
    if ((! modelPath) || (! [[NSFileManager defaultManager] fileExistsAtPath:modelPath])) {
        return;
    }
}
 
- (void)save
{
    [self _updateDefaults];
    
    NSFileManager   *fileManager = [NSFileManager defaultManager];
    
    NSString    *modelDir = [self _modelDir];
    if (![fileManager fileExistsAtPath:modelDir]) {
        NSError *error = nil;
        [fileManager createDirectoryAtPath:modelDir
               withIntermediateDirectories:YES
                                attributes:nil
                                     error:&error];
    }
    
    NSString    *modelPath = [self _modelPath];
    [NSKeyedArchiver archiveRootObject:self.indexArray toFile:modelPath];
}
 
- (void)_clearDefaults
{
    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"version"]) {
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"version"];
    }
}
 
- (void)_updateDefaults
{
    NSString    *versionString = nil;
    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"version"]) {
        versionString = [[NSUserDefaults standardUserDefaults] objectForKey:@"version"];
    }
    if ((versionString == nil) || ([versionString compare:self.version] != NSOrderedSame)) {
        [[NSUserDefaults standardUserDefaults] setObject:self.version forKey:@"version"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}
 
- (void)_loadDefaults
{
    NSString    *versionString = nil;
    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"version"]) {
        versionString = [[NSUserDefaults standardUserDefaults] objectForKey:@"version"];
    }
    if ((versionString == nil) || ([versionString compare:self.version] != NSOrderedSame)) {
        /* バージョン不一致対応 */
    }
    else {
        /* 読み出し */
    }
}
 
- (NSString*)_modelDir
{
    NSArray*    paths;
    NSString*   path;
    paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    if ([paths count] < 1) {
        return nil;
    }
    path = [paths objectAtIndex:0];
    
    path = [path stringByAppendingPathComponent:@".model"];
    return path;
}
 
- (NSString*)_modelPath
{
    NSString*   path;
    path = [[self _modelDir] stringByAppendingPathComponent:@"model.dat"];
    return path;
}
 
@end
ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Hand - GitHub
関連情報 文化を調和させる
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[Swifty]MVCのModel

Try! Swift 2016での発表『文化を調和させる: 関数型プログラミング、プロトコル志向プログラミング、オブジェクト指向プログラミングの優れたテクニックを取り入れる』の手法をXcodeの新規プロジェクト(iOS / Application / Master-Detail Application)で作成されたソースコードに適用してたことをシリーズで発表する。

発表では、データをViewControllerのインスタンス変数として保持したが、自分流では必ずModel(Dataコントローラ)を用意しているので、今回もそうした。

class Document: NSObject {
    static let sharedInstance: Document = {
        let instance = Document()
        return instance
    }()
    
    private override init() {
    }
    
    private let hand = Hand()
}
class MasterViewController: UITableViewController {
 
    var detailViewController: DetailViewController? = nil
    let document = Document.sharedInstance
 
    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.leftBarButtonItem = self.editButtonItem
 
        let addButton = UIBarButtonItem(barButtonSystemItem: .add,
            target: self, action:
            #selector(MasterViewController.addNewCard(sender:)))
        self.navigationItem.rightBarButtonItem = addButton
        if let split = self.splitViewController {
            let controllers = split.viewControllers
            self.detailViewController
                = (controllers[controllers.count-1]
                as! UINavigationController).topViewController
                as? DetailViewController
        }
    }
    :

データをViewControllerのプロパティにしてしまうと、データ管理ができないので、自分は必ずDocumentクラスを用意するようにしている。

ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/Hand - GitHub
関連情報 文化を調和させる
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

Cocoa State of the Union

今年も懲りずにCocoa Advent Calendarを立ち上げました。
今回は、第1日目ということで、自分自身のことを含めて、Cocoa関連について投稿いたします。

* 諸事情で今年からCocoa勉強会の開催方式が変わり、自分が幹事の勉強会は池袋で、ほぼ毎月開催するようになりましたが、逆にこれが活性化に繋がったのではないかと思います。他の勉強会へも積極的に参加するようになり、得るものが大きかったです。
* 以前より、CocoaはmacOS向けという位置付けが強くなったように感じます。
* Carbonとの対比の必要がなくなり、Cocoaと呼ばれなくなったように思えます。
* Apple関連のアプリケーション開発のテクノロジーの興味の流れが、フレームワークから言語、具体的にはSwiftに移ってきましたが、その分、薄くなったように感じます。
* iMessage App Storeのように、新たなビジナスチャンスが現れてきました。
* サーバサイドSwiftが立ち上がろうとしています。ただ、Cocoaのフレームワークがない環境で言語だけ存在して、どういうことになるのか?

二日目以降は、より具体的な内容について投稿していきたいと思います。

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>(ミラー・サイト)<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />

[Playground]Viewをタイムラインに表示

Playgroundでビューをタイムラインに表示してみた。

import Cocoa
import PlaygroundSupport
 
var str = "Hello, playground"
 
var frame = NSRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
var view = NSView(frame: frame)
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.red.cgColor
 
/* 非同期処理の許可 */
PlaygroundPage.current.needsIndefiniteExecution = true
 
/* Viewをタイムラインに表示 */
PlaygroundPage.current.liveView = view
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[macOS]Text To Speech

今回は、以前のアプリをSwift化するだけの内容だ。

テキストの内容を読み上げるが、それにディレイをかける。

import Cocoa
import AudioUnit
import AudioToolbox
import CoreAudioKit
 
class ViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        demo()
    }
    
    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    
    var auGraph: AUGraph? = nil
    
    func demo() {
        var inputNode: AUNode = 0
        var effectNode: AUNode = 0
        var outputNode: AUNode = 0
        
        NewAUGraph(&auGraph);
        
        var	cd = AudioComponentDescription()
        cd.componentType = kAudioUnitType_Generator
        cd.componentSubType = kAudioUnitSubType_SpeechSynthesis
        cd.componentManufacturer = kAudioUnitManufacturer_Apple
        cd.componentFlags = 0
        cd.componentFlagsMask = 0
        
        AUGraphAddNode(auGraph!, &cd, &inputNode)
        
        cd.componentType = kAudioUnitType_Effect
        cd.componentSubType = kAudioUnitSubType_Delay
        AUGraphAddNode(auGraph!, &cd, &effectNode)
        
        cd.componentType = kAudioUnitType_Output
        cd.componentSubType = kAudioUnitSubType_DefaultOutput
        AUGraphAddNode(auGraph!, &cd, &outputNode)
        
        AUGraphConnectNodeInput(auGraph!, inputNode, 0, effectNode, 0)
        AUGraphConnectNodeInput(auGraph!, effectNode, 0, outputNode, 0)
        
        AUGraphOpen(auGraph!)
        AUGraphInitialize(auGraph!)
        
        var generateAudioUnit: AudioUnit? = nil
        AUGraphNodeInfo(auGraph!, inputNode, nil, &generateAudioUnit)
        var channel: SpeechChannel? = nil
        var sz: UInt32 = UInt32(MemoryLayout.size)
        AudioUnitGetProperty(generateAudioUnit!, kAudioUnitProperty_SpeechChannel, kAudioUnitScope_Global, 0, &channel, &sz)
        
        AUGraphStart(auGraph!)
        
        SpeakCFString(channel!, "Nice to meet you. It's nice to see you! Nice meeting you. I'm pleased to meet you. Please say hello to your family. I look forward to seeing you again. Yes. Let's get together soon." as NSString, nil)
    }
    
    func dispose() {
        AUGraphStop(auGraph!)
        AUGraphUninitialize(auGraph!)
        AUGraphClose(auGraph!)
        DisposeAUGraph(auGraph!)
        auGraph = nil
    }
}
関連情報 [Mac]談話と特殊効果(Text-to-Speech)
https://github.com/murakami/TextToSpeech
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[macOS]AU Lab

テキスト文書を読み上げ機能で再生した音声に、CoreAudioのAudio Unitを使ってエフェクトをかける方法を探っていきたいと思う。

まずは、Audio Unitについて調べてみる。

CoreAudioのAudio Unitで出来る事を調べるには、AU Labを使ってみるのが一番だ。

AU Labは、以下から入手できる。

Mastered for iTunes

 

読み上げるテキストを用意する。

 

自由に利用出来るテキストとして、小説『白鯨』がよく使われているが、日本語のテキストだと、青空文庫から入手するのがよいと思う。ただし、文字コードはUTF-8に、開業文字はLFにすること。

入手してテキストをsayコマンドで読み上げる。

$ say -n : -f ./風琴と魚の町.txt

AU Labを起動する。

 

 

"Create Document"を押下し、Editメニューで"Add Audio Unit Generator..."を選択し、AUNetReceiveを追加する。

 

 

AUNetReceiveの接続を押下する。

 

 

追加したGeneratorのEffectsを押下し、メニューでAUDistortionを選択する。

 

 

すると、ディストーションのパラメータが変更できるようになる。

 

 

次は、これをプログラムで行えるようにしてみる。

 

関連情報

Mastered for iTunes

 

【Cocoa練習帳】

http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[bluemix]Arduino Unoを利用した温度センサーを作成する

クラウド温度計の開発を考えている。
今回は、Arduinoで温度を計測するに挑戦だ。

まずは、Arduino。今、入手するとしたらArduino Uno R3ということになるだろう。

次にIDEを入手する。

温度計は、Virtuabotix DHT11。Amazonで探せば色々と見つかると思う。

この温度計には、GNDとNC、DTA、VDDの足が出ていると思うが、ブレッドボードを使うなどして、DHT11のGNDをArduinoのGNDに、VDDを5Vに、DTAをデジタル・ピン2に接続する。

VirtuabotixのサイトからDHT11のライブラリを入手し、IDEに組み込む。

するとサンプルも組み込まれる。IDEの「ファイル > スケッチブック > libraries dht11_functions」を選択して、サンプルを開く。これを実行する。

#include 
 
dht11 DHT11;
 
void setup()
{
  DHT11.attach(2);
  Serial.begin(9600);
  Serial.println("DHT11 TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT11LIB_VERSION);
}
 
void loop()
{
  Serial.println("\n");
 
  int chk = DHT11.read();
 
  Serial.print("Read sensor: ");
  switch (chk)
  {
    case 0: Serial.println("OK"); break;
    case -1: Serial.println("Checksum error"); break;
    case -2: Serial.println("Time out error"); break;
    default: Serial.println("Unknown error"); break;
  }
 
  Serial.print("Humidity (%): ");
  Serial.println((float)DHT11.humidity, DEC);
 
  Serial.print("Temperature (°C): ");
  Serial.println((float)DHT11.temperature, DEC);
 
  Serial.print("Temperature (°F): ");
  Serial.println(DHT11.fahrenheit(), DEC);
 
  Serial.print("Temperature (°K): ");
  Serial.println(DHT11.kelvin(), DEC);
 
  Serial.print("Dew Point (°C): ");
  Serial.println(DHT11.dewPoint(), DEC);
 
  Serial.print("Dew PointFast (°C): ");
  Serial.println(DHT11.dewPointFast(), DEC);
 
  delay(2000);
}

IDEのシリアルモニタを開くと、温度が計測されていることがわかるはずだ。

 

関連情報 Arduino Uno と IBM IoT Foundation を利用してクラウド対 応の温度センサーを作成する: 第 1 回 回路を組み立てて環 境を構築する
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[Cocoa]Cocoa Study at Ikebukuro #3

場所を池袋に移しての三回目の勉強会。 今回の発表は、『NSTableViewのUIを改良する、その1』と『Arduino Unoを利用した温度センサーを作成する』でした。 関連情報 Cocoa Study at Ikebukuro #3
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[Cocoa]Cocoa Study at Ikebukuro #2

場所を池袋に移しての二回目の勉強会。 今回の発表は、『キーボードショートカットキーの拡張』でした。

関連情報
Cocoa Study at Ikebukuro #2

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
note