【Swift 4 x PHP】iOS端末とPHPサーバでHTTP通信

iOS開発初学者です。
[【Swift x PHP】iOS端末とPHPサーバでHTTP通信 - Qiita](https://qiita.com/AkkeyLab/items/ae9b43d3c49b006d5569)の通り作ろうとしたところはまったのでメモっておきます。
まず使っている言語がswift4である自覚がなかった。
swiftはバージョンが上がるごとにいくつかの下位互換性が無くなる様子。

## 1. PHP Server

```php:a.php
<?php 
$title = $_GET["title"];
$note = $_GET["note" ];
print "$title ： $note";
```

```sh:
# 自分のipアドレスを確認
ifconfig | grep mask

# port 8000 でLISTEN
php -S 0.0.0.0:8000
```

IP Addressが`192.168.100.70`であったとして書きます。

試しに、`http://192.168.100.70:8000/a.php?title=タイトル&note=ノート`
とブラウザに入力してアクセス。
`タイトル : ノート`と表示されたら成功です。

## 2. Install Xcode

(略)

## 3. iOS App Development

iOS9以降でセキュリティ的に問題のあるHTTP通信が禁止されているので例外で許可させる。

![スクリーンショット 2017-11-26 10.57.46.png](https://qiita-image-store.s3.amazonaws.com/0/25728/b5541232-fe7a-341e-69b0-a2798d19ce09.png)

Info.plist を右クリックし Source Code として開き、以下を挿入

```xml:Info.plist
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>192.168.100.70</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <false/>
        </dict>
    </dict>
</dict>
```

![スクリーンショット 2017-11-26 10.36.00.png](https://qiita-image-store.s3.amazonaws.com/0/25728/ab0c789f-8c53-daf5-0819-fabae99f9324.png)

追加された事を確認。

![スクリーンショット 2017-11-26 10.57.34.png](https://qiita-image-store.s3.amazonaws.com/0/25728/d0acfe5e-56c8-86c6-9da4-eb5115267551.png)

----

### Main.storyboard

![スクリーンショット 2017-11-26 10.38.05.png](https://qiita-image-store.s3.amazonaws.com/0/25728/024dbdd9-5a5a-3a70-115c-3030f13624ad.png)

### ViewController.swift (swift4 version)

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var resultLabel: UILabel!
    @IBOutlet weak var inputText1: UITextField!
    @IBOutlet weak var inputText2: UITextField!
    
    @IBAction func onButtonTap(_ sender: UIButton) {
        if inputText1.text != "" && inputText2.text != "" {
            let title = inputText1.text!
            let note  = inputText2.text!
            
            let stringUrl = "http://192.168.100.70:8000/a.php?title=\(title)&note=\(note)"
            // Swift4からは書き方が変わりました。
            let url = URL(string: stringUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)!
            let req = URLRequest(url: url)
            
            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
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}
```

## 4. Execute

inputText1,2に文字を入力したあと
ボタンを押すと通信結果がresultLabelに入る事を確認。

![スクリーンショット 2017-11-26 10.42.48.png](https://qiita-image-store.s3.amazonaws.com/0/25728/8a10f26f-a0f4-346e-2e10-7c3a07681aa3.png)