前回(【Swift x PHP】iOS端末とPHPサーバでHTTP通信)のRuby対応版になります。
サーバ側の処理言語としても人気なRuby on Railsに対応させていきましょう!
なんだか今日はハッピーです!Let's try!!
対象
Ruby on Railsの動作環境構築とMVC構成を理解していると良いでしょう。
また、iOS開発に関しても経験があるといいですが、今回作成するアプリをGitHubに上げているので未経験者でも始められると思います。
手順
- お好みのサーバにRuby on Rails環境を構築
- Install xcode
- Clone project file from GitHub
- Execute
1. Rails server
タイトルにRubyとありますが、フレームワークであるRuby on Railsを使っていきます。
Railsの雛形を作ったら、Controllerにparams
を使って、URLに含まれるパラメータを受け取る処理を記述します。出力にはrender
を使います。
render
指定したRHTMLを返す
:text 任意のテキストを指定して表示
params
URLから送られてきた値やフォームで入力した値をparams[:パラメータ名]で取得する
class MainController < ApplicationController
def index
render :text => "#{params[:title]} : #{params[:note]}"
end
end
次に、上記のControllerが呼び出されるようにルーティングの設定を行います。
Rubyは小文字のファイル名、大文字使えるクラス名といった感じのお約束があります。それに従ってController名#メソッド名
という書式でrootに設定しましょう。
Rails.application.routes.draw do
root 'main_controller#index'
end
ここまで出来たら、Rails serverを起動させて以下のようにアクセスしてみましょう。titleパラメータに渡した文字列が表示されたら成功です。
http://192.168.22.2:3000/?title=ありがとう!¬e=これからもよろしくね!
※IPアドレスは臨機応変に変更してください。
2. Install Xcode
Swift3とSwift2のコードを準備しているので準備するXcodeもお好きな方をご準備ください。
Androidほど開発環境構築に時間がかかることはないと思います。
3. iOS App Development
※Serverへの接続先が192.168.2.22
であるものとして記述しているので、臨機応変に変えてください(GitHubのコードも同様です)
まず、iOS9以降でセキュリティ的に問題のあるHTTP通信が禁止されているので例外で許可させておきましょう。HTTPSで通信できるようにサーバを構築した場合はこの作業は必要ありません。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>192.168.2.22</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<false/>
</dict>
</dict>
</dict>
次に、アプリの処理を実際に書いていきます。
clickButton
メソッド内に通信処理を書いています。
ユーザにTextFieldへ送信内容を入力してもらい、その内容を含めたURLでアクセスし、結果を取得・表示するといった流れを記述しています。
UIはお好みで!@IBOutlet
となっている部分がStoryboardとリンクさせてる部分です。
Swift2 version
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var resultLabel: UILabel!
@IBOutlet weak var inputText1: UITextField!
@IBOutlet weak var inputText2: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
inputText1.delegate = self
inputText2.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func clickButton(sender: AnyObject) {
if inputText1.text != "" && inputText2.text != "" {
let title = inputText1.text!
let note = inputText2.text!
// 接続先のURLにパラメータを追加
let stringUrl = "http://192.168.2.22:3000/?title=\(title)¬e=\(note)"
// 文字列のURLからNSURLに変換
let URL = NSURL(string: stringUrl.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!
// NSURLを引数にRequestの生成
let req = NSURLRequest(URL: URL)
// ここからが実際に通信をする所(非同期通信)
let task = NSURLSession.sharedSession().dataTaskWithRequest(req, completionHandler: {
(data, res, err) in
// サーバから出力はありますか?
if data != nil {
// あるみたいだから文字列に変換しておく
let text = NSString(data: data!, encoding: NSUTF8StringEncoding)
// 非同期通信内でUIに変更を加えるときのおまじないと思って!
dispatch_async(dispatch_get_main_queue(), {
self.resultLabel.text = text as String?
})
}else{
// サーバから返事がないみたいだからエラー表示
dispatch_async(dispatch_get_main_queue(), {
self.resultLabel.text = "ERROR"
})
}
})
task.resume()
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool{
//Close keyboard.
textField.resignFirstResponder()
return true
}
}
Swift3 version
Swift3に対応するとともにアラートも追加してみました。
コードの解説はSwift2と変わらないところは省略しています。
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var resultLabel: UILabel!
@IBOutlet weak var inputText1: UITextField!
@IBOutlet weak var inputText2: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
inputText1.delegate = self
inputText2.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func clickButton(_ sender: AnyObject) {
if inputText1.text != "" && inputText2.text != "" {
let title = inputText1.text!
let note = inputText2.text!
let stringUrl = "http://192.168.2.22:3000/?title=\(title)¬e=\(note)"
// Swift3からはNSがなくなってURLになりました
let url = URL(string: stringUrl.addingPercentEscapes(using: String.Encoding.utf8)!)!
// これもNSがなくなりました
let req = URLRequest(url: url)
// ここもNSがなくなりました
let task = URLSession.shared.dataTask(with: req, completionHandler: {
(data, res, err) in
if data != nil {
let text = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
DispatchQueue.main.async(execute: {
self.resultLabel.text = text as String?
})
}else{
DispatchQueue.main.async(execute: {
self.resultLabel.text = "ERROR"
})
}
})
task.resume()
}else{
// 未入力なのにサーバにアクセスしようとしたら怒るようにした
alert("error", messageString: "It is not entered.", buttonString: "OK")
}
}
// 標準のアラートを表示させる
func alert(_ titleString: String, messageString: String, buttonString: String){
//Create UIAlertController
let alert: UIAlertController = UIAlertController(title: titleString, message: messageString, preferredStyle: .alert)
//Create action
let action = UIAlertAction(title: buttonString, style: .default) { action in
NSLog("\(titleString):Push button!")
}
//Add action
alert.addAction(action)
//Start
present(alert, animated: true, completion: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
//Close keyboard.
textField.resignFirstResponder()
return true
}
}
4. Execute
上部に送信した内容がフォーマットされて返ってきているのがわかると思います。
サンプルはPHPバージョンにも対応しています。
【Swift x PHP】iOS端末とPHPサーバでHTTP通信(Qiita)
最後に
Rubyっていいですよね
プログラミング言語としても、宝石としても
サーバ構築とアプリ開発を別の人が担当して共同開発するのもいいですね。きっと面白くなります!!
以下がiOS側のサンプルです。
GitHub | AkkeyLab/SendMessage