getter/setter, CoreDataマイグレーションエラーメモ

本日は Swift ではなく Objective-C です。

というのも、CoreDataの勉強を真面目に始めようと思ったのですが、するならまずはチュートリアルやサンプルが充実しているObjective-Cがよいと思い。 Objective-Cで理解した後、Swift版も作っていきたいと思います。

で、iOS CoreDataチュートリアル(下記)をしていたのですが、CoreData以前に知らないことが多数。。 今回はその時のメモです(CoreDataのことは別の機会に書こうと思うので、今回のは完全に個人用メモです。。)

https://developer.apple.com/jp/devcenter/ios/library/documentation/iPhoneCoreData01.pdf

Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)"
・・・
The model used to open the store is incompatible with the one used to create the store"

ちゃんとマイグレーション処理をしなさい!とのことみたいです。

正統派な対処はまだ良くわかりませんが、とりあえずサンプルでCoreDataこちょこちょいじってるレベルで、今までのデータ全部消えてもよければ、下記のサイトにあるようにファイルを消してしまうのが手っ取り早いです。

CoreData でマイグレーションエラー - 日々是笑心

こちらは実際に試してちゃんと起動できるようになりました。

Highchartsについてのメモ

本日は JavaScript でグラフが簡単に書けるようになるライブラリ「Highchatrs」についてです。

出来上がるグラフは非常に綺麗で、細かい設定も多々できるのですが、なによりびっくりするほど簡単にグラフが作成できます。 ちなみに使うには jQuery が必要です。

どれほど簡単かと言うと、

1 . HTML の記述

Highchatsはjsファイルを1つ読み込むだけでOKです。

<script src="http://code.highcharts.com/highcharts.js"></script>
<div id="chart"></div>

2 . JavaScriptの記述

グラフを表示したい要素に対し highchats を実行し必要なパラメータを渡します。

$(function () {
    $('#chart').highcharts({
        series: [
            {data: [1,3,5,7,9,10,8,6,4,2]},
            {data: [4,5,6,7,8,9,10]}
        ]
    });
});
    

これだけでグラフが出来上がります! こんな感じです。素晴らしいですね!

これなら色々作ってみたくなりますね〜

MWFeedParser を Swift で使ってみる

MWFeedParser は RSS 1.x, 2.x と Atom に対応した parser ライブラリです。 NSXMLParser を利用すると大変なXMLのparseですが、このライブラリなら簡単に解析することができます。

mwaterfall/MWFeedParser · GitHub

興味があって Swift から使ってみました。 基本の基本部分のみの実装ですが https://github.com/・・・/swift_study/tree/master/RssReader_1

その時の手順メモです。

1 . podfile にMWFeedParser を記載(以下) & pod install で MWFeedParser をインストール

pod 'MWFeedParser'

2 . Xcodeを起動し、xxx-Bridging-Header.h(Swift から Objective-Cのクラスやライブラリを使うために必要なファイル)を用意、以下を追記。

#import <MWFeedParser.h>

3 . MWFeedParser を利用する。

ViewControllerにMWFeedParserDelegateをセットします。

その後は、MWFeedParserを使うだけです。一々通信の処理を書かなくても、これだけで対象のURLからXMLを取得しparseを開始してくれます。

let feedURL = NSURL.URLWithString("http://rss.dailynews.yahoo.co.jp/fc/entertainment/rss.xml");
let feedParser = MWFeedParser(feedURL: feedURL)
feedParser.delegate = self
feedParser.parse()

4 . MWFeedParserのdelegateメソッドの実装

parseのタイミングによっていくつかのメソッドが呼ばれるので、それぞれに必要な処理を書きます。 この例では、parse開始時にNSMutableArrayを初期化し、FeedのItemを詰めていきます。parse完了時には tableViewのreloadを実行しています(これでtableViewをfeedItemsの内容に更新)。

// parser 開始
func feedParserDidStart(parser: MWFeedParser) {
    self.feedItems = NSMutableArray()
}
    
// parser 完了時
func feedParserDidFinish(parser: MWFeedParser) {
    self.tableView.reloadData()
}
    
// Feed Info の parse 完了
func feedParser(parser: MWFeedParser, didParseFeedInfo info: MWFeedInfo) {
}
    
// Feed Item の parse 完了(1件毎)
func feedParser(parser: MWFeedParser, didParseFeedItem item: MWFeedItem) {
    self.feedItems.addObject(item)
}

なお、item:MWFeedItem で取得出来る情報は冒頭のURL先にも書かれていますが、titleやlink,Dateなど色々あります。

便利ですね。

Swift 通信を行う方法サンプル

Swiftで通信を行うサンプル

NSxxx を利用する。NSURLSession または、NRURLConnectionが使えるが、iOS7 以降を target にするのであれば NSURLSessionがよいかと.

両者の説明や違いはこちらを参照。

iOS 7で一新された通信周り〜NSURLSessionってなに?〜 | Developers.IO

Swiftでのサンプル

        let url  = NSURL.URLWithString("http://rss.dailynews.yahoo.co.jp/fc/entertainment/rss.xml")
        let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
        let task = session.dataTaskWithURL(url, completionHandler: {
            (data, resp, err) in
            var parser : NSXMLParser = NSXMLParser(data: data)
            parser.delegate = self;
            parser.parse()
        })
        ・・・以降NSXMLParser のdelegateメソッドで解析する

Swift キャプチャリストについてのメモ

続いてキャプチャリストについて

キャプチャリストを使うと、クロージャ内での参照型のオブジェクトのキャプチャルールを定義することができる、とのこと。

以下のような場合循環参照が発生するみたいです。

// self.xxx は 強参照するので、Hoge のインスタンス生成後、インスタンス = nil としてインスタンスからの参照を消してもクロージャからキャプチャされた強参照が残ってしまう。そのため解放されない問題が起きる
class Hoge {
    var hello: String = "Hello"

    lazy var helloWorld:() -> String = {
        self.hello + " World";
    }
}

これに対し、[unowned self] を付与することで強参照しないようにすることができます

    lazy var helloWorld2:() -> String = {
        [unowned self] in return self.hello + " World";
    }

なお、例中の lazy は初期化のタイミングを遅らせる場合に利用するものです。 lazy の指定がない場合、クロージャ内では self 識別子を使うことができません。

勉強させてもらったサイト

Swift のクロージャメモ

Swiftの構文で使われている in が最初何者か分からず調べたメモ(for-inじゃない in です)。

in はクロージャの中で利用され、引数・戻り値と実際の処理の間に記載するもの。 クロージャSwiftでは {} で囲まれたものなので、基本構文はこんな感じ。

{ 引数 -> 戻り値 in <実際の処理>}

なお、Wikipediaを見るところ、クロージャの表記はかなり記載を簡略化できるようで実際に試した結果が以下。便利です!がちゃんと勉強しておかないとなんのこっちゃ、となりそうですね。

        // 配列の各要素にクロージャの処理を実行させる
        let test1:Array<Int> = [10, 20, 30].map({
            (number: Int) -> Int in
            let result = 2 * number
            return result
        })
        
        // 上とやっていることは同じ
        let test2:Array<Int> = [10, 20, 30].map{2 * $0};
        
        // クロージャが1文の場合は return を省略できる。また引数は $0,$1...という記法で扱うことができる
        test1.map({println($0)}) //20, 40, 60
        
        // 結果ももちろん同じ なお、関数の最後がクロージャの場合は () も省略可能みたい。なのでこれでもOK
        test2.map{println($0)} //20, 40, 60

Xcode beta3 から beta5 にしたときのメモ

先日 Xcode を beta3 -> beta5 にしたところ、エラー多数。。

調べてみると、さすが困ったときの stackoverflow & Qiita です 。

一番分からなかった

Class does not implement its superclass's required members

というエラーも

required init(coder aDecoder: NSCoder!) {
  super.init(coder: aDecoder)
}

とすればよい模様。 required というキーワードもまだちゃんとは理解できていないのですが、protocolで宣言したイニシャライザinitは、修飾子requiredが必要となるようです。

その他、beta3 までは StoryBoard から Outlet 接続した際の型に ?/! いずれもついていませんでしたが、beta5 からは ! がつくようになっているようです(たぶん)。 beta3 からのアップデート後は、以前に接続したOutletでコンパイルエラーがでており、?/!いずれかを付与する必要があります。

f:id:espoirka:20140814151705p:plain