こんにちは。
前回の記事でOpenCVのAPIを用意したので、それを使った簡単なiOSアプリを作ります。
GCP + Apache + mod-wsgi + Django 独自ドメインで公開
アプリを作る際に悩むのがネイティブ(Xcode-Swift)かハイブリッド(Phonegap,fultter..)か。。Swiftは触った事がなくて、学習コストが高いので、JavascriptかPythonが使えたらいいのですがPhonegap設定で躓く躓く。。fultterも未経験でSwift同様で学習コストが高いので、もう腹をくくってネイティブ(Xcode-Swift)で行ってみます。フォトライブラリーを起動して写真を選択して、その写真をAPI向けにアップロードして結果を受け取り、処理する。だけのシンプルアプリだから、大丈夫でしょう。
まぁ、世の中そんなに甘くないよね。
Swiftクセが強い(笑)
なので、今回は以下2点に絞ってお話します。
・APIにPOSTして結果をJSONで受取る
・非同期処理のAPIの結果を待って処理する
APIにPOSTして結果をJSONで受取る
API呼び出してJSONで受取るFuncを作ります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| func processAsyncFaceDetect(image: UIImage?){
var face: FaceDect?
let url = URL(string: "http://[api url]")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let boundary = UUID().uuidString
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var uploadData = Data()
uploadData.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
uploadData.append("Content-Disposition: form-data; name=\"image\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
uploadData.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
uploadData.append((uploadimage?.jpegData(compressionQuality: 1.0)!)!)
uploadData.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
session.uploadTask(with: request,from: image) { data, response, error in
DispatchQueue.global().async {
if(error != nil){
print("\(error!.localizedDescription)")
}
face = try! JSONDecoder.init().decode(FaceDect.self, from: data!)
}
}.resume()
}
struct FaceDect: Decodable {
var success: Bool
var num_faces: Int?
let faces: [[Int]]?
}
|
非同期処理のAPIの結果を待って処理する
APIの結果を使いたいので、結果を待って次の処理をするようにします。
ちなみにこちらのサイトを殆どコピーさせて頂きました。ありがとうございます。
APIの結果が入ったらそれを通知するようにします。以下色付き行(1,29行目)の部分を変更します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| func processAsyncFaceDetect(image: UIImage? ,_ after:@escaping (FaceDect) -> ()){
var face: FaceDect?
let url = URL(string: "http://[api url]")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let boundary = UUID().uuidString
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var uploadData = Data()
uploadData.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
uploadData.append("Content-Disposition: form-data; name=\"image\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
uploadData.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
uploadData.append((uploadimage?.jpegData(compressionQuality: 1.0)!)!)
uploadData.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
session.uploadTask(with: request,from: uploadData) { data, response, error in
DispatchQueue.global().async {
if(error != nil){
print("\(error!.localizedDescription)")
}
face = try! JSONDecoder.init().decode(FaceDect.self, from: data!)
after(face !)
}
}.resume()
}
struct FaceDect: Decodable {
var success: Bool
var num_faces: Int?
let faces: [[Int]]?
}
|
上記の非同期処理Funcを作成したら、それを同期処理にするFuncを作成します。
1
2
3
4
5
6
7
8
9
10
| func processSyncFaceDetect(image: UIImage?) -> FaceDect? {
var result: FaceDect?
let semaphore = DispatchSemaphore(value: 0)
processAsyncFaceDetect(image: image) { (facerect: FaceDect) in
result = facerect
semaphore.signal()
}
semaphore.wait()
return result
}
|