-->

Mac

JSONSerializationというクラスがあってこれを使う。
JSONの文字列からオブジェクト(ArrayやDictionary)に変換する。

        let jsonStr = "[ { \"name\":\"山田太郎\", \"age\":22 }, { \"name\":\"山田花子\", \"age\":24 } ]"
        // JSON文字列をNSDataに変換
        let jsonData = jsonStr.data(using: String.Encoding.utf8)
        do {
            // DataからJSONオブジェクトに変換
            let json = try JSONSerialization.jsonObject(with: jsonData!, options: .mutableLeaves) as! Array<Dictionary<String, Any>>
            for item in json {
                if let name = item["name"], let age = item["age"] {
                    print("\(name):\(age)")
                }
            }
        } catch {
        }

オブジェクトをJSON(文字列)に変換する。オブジェクトは、NSArray、NSDirctionaryでその中の値は、NSString、NSNumber、NSDictionary、NSNullでNSDictionaryのキーはNSStringじゃないといけない。

        let json = [
            [ "name":"山田太郎", "age":22 ],
            [ "name":"山田花子", "age":24 ]
        ]
        do {
            if JSONSerialization.isValidJSONObject(json) {  // JSONに変換できるかチェック
                // JSONに変換(.prettyPrintedを指定すると見やすいように改行や空白が挿入される。)
                let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
                // ↓こっちだと空白や改行が含まれない
//                let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
                // Dataを文字列に変換する。
                let jsonStr = String.init(data: jsonData, encoding: .utf8)
                if let str = jsonStr {
                    print(str)
                }
            }
        } catch {
            
        }



このエントリーをはてなブックマークに追加

とりあえず、URLSessionを使って通信してみる。(たぶん一番単純なもの)

macOS向けに書くがiOSでも基本的に同じだ。

ボタンを貼ってそれを押した時の処理をこんな感じにする。

    @IBAction func buttonClick(_ sender: NSButton) {
        let url = URL(string: "http://www.livedoor.com/")
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        let req = URLRequest(url: url!)
        
        let task = session.dataTask(with: req, completionHandler: {
            (data, res, err) in
            if let uerr = err {
                print(uerr.localizedDescription)
            }
            if let udata = data {
                let str = String(data: udata, encoding: String.Encoding.utf8)
                print(str ?? "エラー")
            }
        })
        task.resume()
    }

これを実行するとこんなエラーがでる。

2017-02-07 23:04:07.107 TestHttp[71203:1144451] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

App Transport Security(ATS)によってHTTP通信をブロックしてるって書いてある。基本的にHTTPS通信しろと言うことだ。
例外的にこれを解決するにはInfo.plistを変更する必要がある。何種類か方法があるが何個か書いておく。

非推奨の方法

App Transport Security Settingsを追加してその下にAllow Arbitrary Loadsを追加してYESにする。

002

例外ドメインを追加する方法

App Transport Security SettingsにException Domainsを追加してDictionary型でドメイン(ここではwww.livedoor.com)を追加する。NSTemporaryExceptionAllowsInsecureHTTPLoads、NSIncludesSubdomainsをBoolean型でYESで追加する。

003

次にTextViewに受信したデータを表示してみよう。
UI部品を操作するにはメインスレッドで行う必要があるのだが、dataTaskに指定するクロージャは別スレッドで実行されるのでDispatchQueue.main.asyncを使ってアクセスする。TextViewをはっ付けてtextViewでアクセスできるようにして、次のコードをprint(str ?? "エラー")の次あたりに追加する。

                DispatchQueue.main.async {
                    self.textView.string = str
                }

(追記)
DispatchQueue.main.asyncより、OperationQueue.main.addOperationの方がいいのかな。



このエントリーをはてなブックマークに追加

[macOS] テーブルビューを使ってみる。(1)では、Cell Basedでやったんだが、View Basedでやってみる。

[macOS] テーブルビューを使ってみる。(1)と同じようにやっていく。

違うところは、
ViewControllerクラスにNSTableViewDataSourceプロトコルとNSTableViewDelegateプロトコルを追加する。

func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?

の代わりに

func tableView(_ tableView: NSTableView,  viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?

を実装する。

    // 表示するデータをセットしたViewを返す。
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let cell = tableView.make(withIdentifier: (tableColumn?.identifier)!, owner: self) as! NSTableCellView
        if let tcol = tableColumn {
            if(tcol.identifier == "Name") {
                cell.textField?.stringValue = datas[row].name
            } else if(tcol.identifier == "Age") {
                cell.textField?.stringValue = "\(datas[row].age)"
            }
        }
        return cell
    }

TableViewのContent ModeをView Basedにする。
TableViewのdelegateもView Controllerに接続する。

こんなところだ。



このエントリーをはてなブックマークに追加

iOSの[iOS] 画面遷移(値を渡す)と基本的に同じだ。Cocoa Touch Classで新規にファイルを作る代わりにCocoa Classで作るのとUIViewControllerのところをNSViewControllerと読み替えて同じようにする。

ViewController2.swiftはこんな感じだ。

import Cocoa

class ViewController2: NSViewController {
    @IBOutlet weak var label: NSTextField!
    
    var message = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        label.stringValue = message
    }
    
}

ViewControllerクラスに追加するコードはこんな感じだ。

    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
        let viewController2 = segue.destinationController as! ViewController2
        viewController2.message = "PAGE2"
    }


このエントリーをはてなブックマークに追加

[macOS] 画面遷移(というか別の画面を出す)の続きでページ2のウインドウを閉じれるようにしようと思う。

ストーリボードを開いてページ2にボタンをはっ付ける。
ページ2のボタンをctrlキーを押しながらページ2の上の方にあるView Controllerのアイコンにドラッグ&ドロップする。表示されるポップアップメニューでdismissControllerを選ぶ。

001

これで実行してページ2を表示、ボタンを押すとページ2が閉じる。(Modal、Sheet、Popoverのとき。Showのときは閉じない)


このエントリーをはてなブックマークに追加

↑このページのトップヘ