Edited at

[Swift]Parseで簡単 DB連携でTwitter作成

More than 3 years have passed since last update.


Parseとはなんぞや

バックエンドをswift(Obj-c)だけで簡単に実装できてしまうもの。

ここではざっくり説明していきます。

詳しくはParse iOS Guidをみて下さい。

ParseのDBの接続部分だけ見たい方は目次の[ParseDB連携]で飛んで下さい。


作成するアプリ

Twitterのようなアプリを作成しながら、Parseのありがたさを見ていきます。

メインはParseで用意されているDB(データベース)に保存するところですね。

名称未設定.png


Parse.comに新規登録

まずは、Parse.comに登録します。

登録完了したら、ホーム画面の右上の『Go to your apps』をクリック。

Parse_と_Parseを使ってみよう.png


次の画面では、Parse上にアプリ新しく作ります。その時に、アプリ名を設定します。

Home___Parse.png


作成されたアプリをクリックすると...

Home___Parse.png


アプリの管理ページが登場

Analytics___Parse.png

ここのページで保存したデータなどを確認するわけですねえ。

ここまでで、一旦Parse側の操作は終わりです。


Xcode側で新規プロジェクトを作成

いつものように、Xcodeのプロジェクトを作ります。


SDKのインポート

作成したプロジェクトにParseに用意されている、SDKをインポートします。

Prase.comに戻り、アプリ管理ページの下部の[Downloads]をクリック

Analytics___Parse.png


SDKをクリックすると、SDKをダウンロードすることができます。

Downloads___Changelogs___Parse.png


ダウンロードしたzipファイルを解凍し、その中の以下の2つのファイルをXcodeにドラッグ&ドロップでインポートしましょう。


  • Parse.framework

  • Bolts.framework


その他の必要なフレームワークをインポート

先程の2つのフレームワーク以外に必要なものをインポートします。

以下の画像のように、Linked Frameworks and Libraries まで行き、必要なフレームワークを追加します。

追加するファイル以下のものです。


  • AudioToolbox.framework

  • CFNetwork.framework

  • CoreGraphics.framework

  • CoreLocation.framework

  • MobileCoreServices.framework

  • QuartzCore.framework

  • Security.framework

  • StoreKit.framework

  • SystemConfiguration.framework

  • libsqlite3.dylib

  • libz.dylib


Parseで作成したアプリとXcodeのプロジェクトの紐付け

現段階では、Parse.comで作成したアプリと、Xcodeで作成したプロジェクトは独立しているので、

Parse.comで発行される、keyを用いて紐付けます。


Parse.com

Edit_Your_App___Parse.png


  • Application ID

  • Client Key

この2つを使用します。


Xcodeプロジェクト

AppDelegate.swiftに以下のように編集します。


AppDelegate.swift

import UIKit

import Parse //Parseをインポート

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

//Parseで取得した[Application ID]と[Client Key]を指定
Parse.setApplicationId("[Application ID]", clientKey: "[Client Key]")

return true
}


以上の操作で、連携は完了です。


UIの作成と必要なSwiftファイルの追加

Main.storyboard上はざっくりこんな感じです。

Main_storyboard_と_PracticeParseLogin_xcodeproj.png


必要なファイルを作成します。


  • Models


    • Tweet.swift(NSObject)

    • TweetManager.swift(NSObject)



  • Views


    • TweetTableViewCell.swift(UITableViewCell)

    • TweetTableViewCell.xib




  • ViewControllers


    • TweetsTableViewController.swift(UITableViewController)

    • NewTweetViewController.swfit(UIViewController)




今回は、Parseで用意さえたDBとの接続がメインなので、それ以外の部分はざざざっと書いていきます。


Tweet.swft

import UIKit

import Parse

class Tweet: NSObject {
var name: String!
var text: String!

init(name: String, text: String) {
self.name = name
self.text = text
}

func saveTweet() {
//後ほどParseのdbに保存する処理を書く
}
}



TweetManager.swift

import UIKit

import Parse

class TweetManager: NSObject {

var tweets: Array<Tweet> = []
static let sharedInstance = TweetManager()

func fetchTweets(callback: () -> Void) {
//後ほどParseのdbからツイート情報を取得する処理を記述
}
}



TweetTableViewCell.swift

import UIKit

class TweetTableViewCell: UITableViewCell {
@IBOutlet weak var tweetLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var tweetImageView: UIImageView!

override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
tweetLabel.numberOfLines = 0
tweetImageView.clipsToBounds = true
tweetImageView.contentMode = UIViewContentMode.ScaleAspectFill
}

override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}


import UIKit

class TweetsTableViewController: UITableViewController {

let tweetCollection = TweetManager.sharedInstance

override func viewDidLoad() {
super.viewDidLoad()

tableView.registerNib(UINib(nibName: "TweetTableViewCell", bundle: nil), forCellReuseIdentifier: "TweetTableViewCell")
tableView.estimatedRowHeight = 90
tableView.rowHeight = UITableViewAutomaticDimension
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "New", style: UIBarButtonItemStyle.Plain, target: self, action: "showNewTweetViewController")
let callback = { () -> Void in
self.tableView.reloadData()
}
tweetCollection.fetchTweets(callback)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tweetCollection.tweets.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TweetTableViewCell", forIndexPath: indexPath) as! TweetTableViewCell
let tweet = tweetCollection.tweets[indexPath.row]
cell.tweetImageView.image = UIImage(named: "omoto")
cell.nameLabel.text = tweet.name
cell.tweetLabel.text = tweet.text
return cell
}

func showNewTweetViewController() {
performSegueWithIdentifier("toNewViewController", sender: nil)
}

override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
}


NewTweetViewController.swift

import UIKit

class NewTweetViewController: UIViewController, UITextViewDelegate {

@IBOutlet weak var placeholderLabel: UILabel!
@IBOutlet weak var tweetButton: UIButton!
@IBOutlet weak var tweetTextView: UITextView!
@IBOutlet weak var nameTextfield: UITextField!

override func viewDidLoad() {
super.viewDidLoad()
tweetTextView.delegate = self
tweetButton.layer.cornerRadius = 5
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

func textViewShouldBeginEditing(textView: UITextView) -> Bool {
placeholderLabel.hidden = true
return true
}

func textViewShouldEndEditing(textView: UITextView) -> Bool {
if textView.text.isEmpty {
placeholderLabel.hidden = false
}
return true
}

@IBAction func tapTweetButton(sender: UIButton) {
if nameTextfield.text.isEmpty || tweetTextView.text.isEmpty {
println("Name or text is empty")
} else {
let tweet = Tweet(name: nameTextfield.text, text: tweetTextView.text)
tweet.saveTweet()
navigationController?.popViewControllerAnimated(true)
}
}
}


一旦ここまで。


ParseのDB連携

いよいよ今回のメインです。


DBにデータを保存

Tweet.swiftのsaveTweet()を編集していきます。


Tweet.swft

import UIKit

import Parse

class Tweet: NSObject {
var name: String!
var text: String!

init(name: String, text: String) {
self.name = name
self.text = text
}

func saveTweet() {
let tweetsObject = PFObject(className: "tweets")
tweetsObject["name"] = name
tweetsObject["text"] = text
tweetsObject.saveInBackgroundWithBlock { (success, error) -> Void in
if success {
println("Tweet has been saved")
}
}
}
}


それぞれ解説していきます。

PFObject(className: "tweets")では引数に指定した名前のクラスがParse上に存在すればそのオブジェクトを取得し、無ければ生成してくれます。

tweetsObject["name"] = nameでは、作成したテーブルに name という名前のカラムを作成し、値を保存しています。

最後にsaveInBackgroundWithBlock()メソッドによって、非同期でDBに値を保存します。


DBから値の取得

続いて、保存した値を取得しましょう。TweetManager.swiftのfetchTweets()メソッドを編集します。


TweetManager.swift

import UIKit

import Parse

class TweetManager: NSObject {

var tweets: Array<Tweet> = []
static let sharedInstance = TweetManager()

func fetchTweets(callback: () -> Void) {
let query = PFQuery(className: "tweets")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock { (tweets, error) -> Void in
if error == nil {
self.tweets = []
for tweet in tweets as! Array<PFObject> {
let name = tweet["name"] as! String
let text = tweet["text"] as! String
let tweet = Tweet(name: name, text: text)
self.tweets.append(tweet)
}
callback()
}
}
}
}



let query = PFQuery(className: "tweets")

DBから作成したオブジェクトを取得するためには、PFQueryを使用しています。

query.orderByDescending("createdAt")

取得した複数のオブジェクトを並び替えています。

findObjectsInBackgroundWithBlock()メソッドにてDBから実際にツイートのデータを全て非同期で取得します。

後は取得すたツイートでデータを作成したTweetモデルに変換し、配列に保存しています。


Parse上で保存したデータの確認

Banners_and_Alerts_と_tweets___Parse.png

ツイートしたデータを確認することができました。



次回予告

次回はParseを使ったログイン機能の実装を紹介しちゃうぞえ