swift4でARアプリを作ろう

まず、Augmented Reality Appを選択する必要がある。

AppDelegate.swift, ViewController.swift, Main.storyboard, LaunchScreen.storyboard, Info.plist は同じだが、art.scnassetsが追加されている。

viewController.swift
デフォルトでvr体験できるようになってますね。

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        // Set the scene to the view
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    // MARK: - ARSCNViewDelegate
    
/*
    // Override to create and configure nodes for anchors added to the view's session.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
     
        return node
    }
*/
    
    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        
    }
    
    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
        
    }
    
    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
        
    }
}

NIFCloud-mbaasをx-codeに入れよう

githubを開きます。
https://github.com/NIFCloud-mbaas/ncmb_ios/releases

最新版のv2.4.3をダウンロードします。
プロジェクトフォルダのxxx.xcodeprojと同じ階層にダウンロードしたフォルダncmb_ios-2.4.3を置きます。

x-codeを立ち上げて、xxxx.xcodeprojから、Build Phasesを開く。

Link Binary With LibrariesでNCMBを開く。

続いて、AppDelegate.swiftと同じディレクトリにxxx-Bridging-Header.hを作成する。

あ、NBCM.frameworkでないとダメのようですね。

はあ?エラーが消えた!!!
なにこれ?

APNs(Apple Push Notification Service)

1.ユーザーがpush通知許可
2.APNsがユーザーにデバイストークンを発行
3.ユーザーがサーバーにデバイストークン登録
4.サーバーがAPNsにプッシュ通知
5.APNsがユーザーにpush通知

サーバーはニフティクラウド mobile backendを使うらしい。
http://mb.cloud.nifty.com/
mBaaSというらしい。

とりあえず、登録してましょう。

ああ、これかー、application keyとclient key

macキーチェーンアクセスでCSR(Certificate Signing Request)を取得する

まず、キーチェーンアクセスって何処にある?ジャッキーチェーン?

最初に、Utilitiesを開きます。

utilitiesから、Keychain Accessを開きます。
なんだ、簡単。

次に、Keychain Accessから、Certificate Assistant -> Request a Certificate From a Certificate Authority… を開きます。

Certificate Informationのformが開くので、User Email Addressにmacのdeveloperで登録しているメールアドレス、CA Email Addressは空欄、Request is:は、saved to disk と Let me specifiy key pair informationをチェックします。

そうすると、保存場所を聞かれるので、適当にDesktopにでも保存します。

key pair informationはそのまま、RSA 2048bitでcontinueします。

できました。OK

push通知を実装する

AppDelegate.swift で、UserNotifications, NCMBをimportする。

import UIKit
import UserNotifications
import NCMB

あれ、NCMBがインポートできない。
あれ、証明書が必要なの?

>証明書の取得
>参考1(GitHub):プッシュ通知の受信に必要な証明書の作り方(開発用)
>参考2(Qiita):プッシュ通知に必要な証明書の作り方2016
>ニフクラ mobile backend の無料登録(アカウント取得)
なに、事前準備がこんなにあるのか。。

そもそもCSRファイルとは?
>CSR には「公開鍵」とその所有者情報、及び申請者が対応する秘密鍵を持っていることを
>示すために申請者の署名が記載されています。 認証局は証明書にその所有者情報を
>署名することで、所有者の存在を証明しています。
>SSL 通信ではサーバが公開鍵を提示し、これを用いて暗号化通信を開始します。
公開鍵、所有者情報、秘密鍵を持っていることの証明か。

そもそも、CSRってなんの略? まさか企業の社会的責任じゃないよね? Corporate Social Responsibility?

Certificate Signing Request ですと。よかったー、安心♪

swiftでhttp通信

info.plistに追加します。

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>http://hpscript.com/</key>
            <dict>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <false/>
            </dict>
        </dict>
    </dict>

php

$response = array();

if($_SERVER['REQUEST_METHOD'] == 'POST'){
	$teamName = $_POST['name'];
	$member = $_POST['old'];

	$response['api'] = "succeeded";
	$response['member'] = $member . " years old!";
	echo json_encode($response);
}

xcode console
っキタキタキタ!!!!!!!!!!!!!!!!!!!!!!!!

今回、php側はjsonで返してますが、mysqlへのinsert, fetchResultもできますね。iOSの光が見えてきた。

swiftでpostする

import UIKit

class ViewController: UIViewController {
    let URL_SAVE_BOY = "http://hpscript.com/swift/index.php"
    
    @IBOutlet weak var NameFeild: UITextField!
    @IBOutlet weak var oldFeild: UITextField!
    
    @IBAction func saveBtn(_ sender: Any) {
        let requestURL = NSURL(string: URL_SAVE_BOY)
        let request = NSMutableURLRequest(url: requestURL! as URL)
        
        request.httpMethod = "POST"
        
        let teamName = NameFeild.text
        let memberOld = oldFeild.text
        
        let postParameters = "name="+teamName!+"&old="+memberOld!;
        
        request.httpBody = postParameters.data(using: String.Encoding.utf8)
        
        let task = URLSession.shared.dataTask(with: request as URLRequest){
            data, response, error in
            
            if error != nil {
                print("error is \(error)")
                return;
            }
            
            do {
                let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
                
                if let parseJSON = myJSON {
                    var msg : String!
                    msg = parseJSON["message"] as! String?
                    print(msg)
                }
            } catch {
                print(error)
            }
        }
        task.resume()
    }
    
    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.
    }
}

textFieldの値をpostしてreturnのjsonをparseする

URL.httpMethod = “POST”, postdata.data(using: String.Encoding.utf8) とします。
URLSession.shared.dataTask(with: request as URLRequest)

viewController.swift

let URL_SAVE_BOY = "http://www.hogehoge/api/savBoy.php"
    
    @IBOutlet weak var NameFeild: UITextField!
    @IBOutlet weak var oldFeild: UITextField!
    
    @IBAction func saveBtn(_ sender: Any) {
        let requestURL = NSURL(string: URL_SAVE_BOY)
        let request = NSMutableURLRequest(url: requestURL! as URL)
        
        request.httpMethod = "POST"
        
        let teamName = NameFeild.text
        let memberOld = oldFeild.text
        
        let postParameters = "name="+teamName!+"&old="+memberOld!;
        
        request.httpBody = postParameters.data(using: String.Encoding.utf8)
        
        let task = URLSession.shared.dataTask(with: request as URLRequest){
            data, response, error in
            
            if error != nil {
                print("error is \(error)")
                return;
            }
            
            do {
                let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
                
                if let parseJSON = myJSON {
                    var msg : String!
                    msg = parseJSON["message"] as! String?
                    print(msg)
                }
            } catch {
                print(error)
            }
        }
        task.resume()
    }

swiftとmysqlを連携する

まず、mysqlにdbをつくります。適当に、swiftとしておきます。

table名はどうしましょう。まあ、後で考えます。
続いて、phpファイルをvagrantにつくっていきます。
フォルダはapiとincludes


ok!

では、phpをつくっていきます。

swift4でyoutube api

import UIKit
import Alamofire

class Model: NSObject {
    private var youtubeNextPageToken: String?
    
    func loadYoutubeList(callback: (youtubeList: YoutubeList) -> (), fail:((error: NSError) ->())){
        
        let req = request(.GET, AppConfig.youtubeURL())
        req.response { (request, response, responseData, error) -> Void in
            do {
                let jsonResult = try NSJSONSerialization.JSONObjectWthData(responseData!, options: NSJSONReadingOptions.MutableContainers) as! NSMutableDictionary
                
                self.youtubeNextPageToken = jsonResult["nextPageToken"] as! String?
                let ary = jsonResult["items"] as! NSArray
                let youtubeList = YoutubeList(ary: ary)
                callback(youtubeList: youtubeList)
            } catch {
                print("loadYoutubeList error")
            }
        }
    }
}

constrainをつけて行きます。