Skip to content

Instantly share code, notes, and snippets.

@non117
Created October 26, 2016 13:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save non117/5676d1fcf3bab869d1af269098f00df1 to your computer and use it in GitHub Desktop.
Save non117/5676d1fcf3bab869d1af269098f00df1 to your computer and use it in GitHub Desktop.
OCRくん
//
// OCRClient.swift
// ReceiptManager
//
// Created by non on 2016/10/10.
// Copyright © 2016年 non. All rights reserved.
//
import Foundation
import Alamofire
public class OCRClient {
let HOST = "https://vision.googleapis.com"
let ANNOTATE_API = "/v1/images:annotate"
var api_key: String
init(api_key: String){
self.api_key = api_key
}
// MARK: - main request method
func annotate(image: Data) -> AnnotatedResponse? {
let parameters: Parameters = [
"requests": [
"image": [
"content": image.base64EncodedString()
],
"features": [
[
"type": "TEXT_DETECTION",
"maxResults": 2
]
]
]
]
let url = HOST + ANNOTATE_API + "?key=" + api_key
var annotatedResonse: AnnotatedResponse?
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).validate().responseJSON {
response in
print(response)
if let json = response.result.value {
annotatedResonse = try? AnnotatedResponse.decodeValue(json)
}
}
return annotatedResonse
}
// MARK: - convenience request
func annotate(imagePath: URL) -> AnnotatedResponse? {
let image = try! Data.init(contentsOf: imagePath)
return annotate(image: image)
}
}
@non117
Copy link
Author

non117 commented Oct 26, 2016

39-45行目が実行されていない様子

@non117
Copy link
Author

non117 commented Oct 26, 2016

var annotatedResonse: AnnotatedResponse? を消したら動いた……。

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

まず L15 の varlet で書けると思う。
そもそも文字列結合で URL を作るのは悪手なので URL の便利メソッドを使った方がいい。 NSURL でググれば有用な情報出てきそうだし、 Swift Standard Library の URL の項目を読むのでも良い。

Alamofire の使い方が分からないのでなんとも言えないんだけど、これは多分非同期で実行されるので annotatedResonse は nil のまま即座に return されて、その後通信が成功してレスポンスがなんやかんやしたあとにクロージャの中が実行されると思う。

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

あとどうでもいいけど L51 の

Data.init(contentsOf: imagePath)

だけど Swift は明示的に init って書かない感じが流行りなので

Data(contentsOf: imagePath)

の方が見栄えが言いと思う。

あと OCRClient はこれだけなら class である必要はなくて struct で書いて良さそう。Swift における class と struct は C 言語とかその他の言語のそれらとは概念が全然違っていて、値型か参照型かの違いくらいしかなくて、滅多なこと(Objective-C に依存する場合とか)が無い限り値型の struct で書いて Copy on Write とコンパイラの最適化に任せた方が速い。

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

なんか重箱の隅ばっかだけどスネークケースな api_key より apiKey の方が Swift 感ある。
それから

let HOST = "https://vision.googleapis.com"
let ANNOTATE_API = "/v1/images:annotate"

はこの書き方だとインスタンスに紐付く定数なんだけど、意味的にはもっと大域でも良さそうなのでクラスに紐付くように

static let HOST = "https://vision.googleapis.com"
static let ANNOTATE_API = "/v1/images:annotate"

って書いた方が伝わる感じがする

@non117
Copy link
Author

non117 commented Oct 26, 2016

Alamofire の使い方が分からないのでなんとも言えないんだけど、これは多分非同期で実行されるので annotatedResonse は nil のまま即座に return されて、その後通信が成功してレスポンスがなんやかんやしたあとにクロージャの中が実行されると思う。

なるほど!!!!

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

まだ重箱なんだけど

func annotate(image: Data) -> AnnotatedResponse?

image って変数名、そのままだと UIImage とか NSImage の型かな?みたいになって混乱するから imageData みたいな名前の方が好まれそうな気はする。

@non117
Copy link
Author

non117 commented Oct 26, 2016

文化ぜんぜん知らんので重箱の隅助かる

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

このくらいの規模なら Alamofire はライブラリとして超ファットに思えるので APIKit を使うのがお洒落感あるし、そもそも AlamofireAPIKit も Apple が提供してる FoundationNSURLSession (Swift 3 では URLSession) の厚いラッパと薄いラッパなのと、URLSession の使い方は簡単なので無理に外部のライブラリに依存することはない気もする。

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

APIKitNSURLSession を Swift の型の世界観に上手くお洒落に合わせるように薄く作られたイケてるライブラリという感じと言った方が良いか。

Alamofire は前身が AFNetworking ってライブラリなんだけど、とにかく全部入りを目指してる(ただし NSURLSession がそもそも全部入り)ライブラリで、AFNetworking は昔オプションの指定をアレして脆弱性を作り込んでしまった過去とかもある。
ので最近は全部入りな通信回りを任せるライブラリを使うのはやめようみたいな風潮があるというか、そもそも NSURLSession で全部出来るじゃんということに皆が気付き始めたという感じ。

@non117
Copy link
Author

non117 commented Oct 26, 2016

AFNetworking は昔オプションの指定をアレして脆弱性を作り込んでしまった過去とかもある。

厳しい。。。

この程度の規模のAPIなら題材としても楽だし、今コスト払って公式ライブラリ使えるようになっていたほうが良さそうだね。

@dnpp73
Copy link

dnpp73 commented Oct 26, 2016

NSURLSession の簡単な話をすると、NSURL を放り込むと色々と OS がキューイングとか QoS とかややこしいことを肩代わりしてレスポンスを返してくれるよ、ってやつで、 iOS では 7 以降から、 macOS では 10.9 以降から使えるようになったもの。
それまで古代人達は NSURLRequest ってやつを使って、それに NSURL を放り込んでた。
NSURLSession になってややこしいことを割と OS 側に投げられるようになってみんなハッピーになったという過去がある。

んで、 NSURLSessionNSURLRequest は別に HTTP に限定されてなくて、バイナリとかも放り投げられるしソケット通信も出来る(はず、あまり使わないから忘れた)。
現代人は概ね HTTPS による通信で安全にテキストをやり取りするだろうから、古代人のようにバイナリをソケット通信で投げ合うなんて野蛮なことはしないので、NSURLSession の中の httpssl に関する一部の機能が上手く使えれば良い、という気持ちでドキュメントを読むとすんなり理解出来そうな気はする

@applideveloper
Copy link

applideveloper commented Nov 30, 2016

ネットワークライブラリ使わずに自作ネットワークライブラリつくって自分で脆弱性つくり込むより、メンテナンスされたライブラリ使った方がいいとも思いますけどね

@applideveloper
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment