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
getter/setter
@synthesize と言った文(コンパイラディレクティブ)がよく分からなかったのですが、@propertyと合わせてgetter/setterが利用できるようになるようです。詳しい説明はこちら!
Objective-Cの @property と @synthesize の組み合わせが何をやっているのかを解説 - 強火で進め
CoreData のマイグレーションエラー
CoreDataを利用する上で、エンティティを少しでも変更するとアプリ起動時にエラーが発生してしまいます。
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こちょこちょいじってるレベルで、今までのデータ全部消えてもよければ、下記のサイトにあるようにファイルを消してしまうのが手っ取り早いです。
こちらは実際に試してちゃんと起動できるようになりました。
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 です 。
- SwiftのXcode6-β5で発生したエラー解決策への疑問 - Qiita
- Objective-C - Swift開発でXcode6 Beta5にアップデートしたらたくさんコンパイルエラーになった - Qiita
- iOS8 - Swiftの継承についての簡単な整理 - Qiita
- ios - Swift: Class does not implement its superclass's required members - Stack Overflow
一番分からなかった
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でコンパイルエラーがでており、?/!いずれかを付与する必要があります。