こんにちは
最近になってようやくSwiftUIを触り始めたので、この機会にということで、MacCatalystにも挑戦してみました
すごくざっくり言えば、iOSとMacのアプリが同じコードで動くということです
実際触ってみた感想で言えば、夢を見過ぎるべきでないということですかね
というわけで、導入してみましょう
何を作る?
所用でTwitterのAPIの申請を作成することになったんですが、その申請って英語なんですよね
英語力が死んだ自分には、書くのはしんどいので(そもそもあれ大して読まれてないって説もありますがどうなんですかね)翻訳ソフトに頼りますが、Google翻訳は信用してないので、NICTのAPIを使うことにします
そして、あのWebサイト、時間制限があるんですよね(24分間)
かといって、メモとかに残すのもだるいので、ネイティブアプリでAPIを叩く感じにします
プロジェクトの作成
プロジェクトの作成方法としては、iOSと一緒です
[f:id:beah:20200224202637p:plain]
User Interface
をSwiftUI
にするのを忘れないであげてください
[f:id:beah:20200224202826p:plain]
Deploy Info
のTarget
のMac
にチェックを入れます
[f:id:beah:20200224202933p:plain]
メッセージが出るのでEnable
をクリックします
プロジェクトのMac対応は以上です
[f:id:beah:20200224203048p:plain]
Deviceの一覧に、MacとiPhone/iPadが共存しているの、なんか新鮮ですよね
両方で動くんだという実感が湧きます
SwiftUI
import SwiftUI
struct ContentView: View {
@State private var rawText = ""
@State private var translatedText = ""
var translationController = TranslationController(apiKey: "YOUR API KEY",
apiSecret: "YOUR API SECRET",
apiUserName: "YOUR USER NAME")
var body: some View {
VStack{
TextField("翻訳元", text: $rawText)
.padding(.horizontal)
Button(action: {
let (parameter, url) = self.translationController.generateParameter(fromLang: "ja", toLang: "en", text: self.rawText)
self.translationController
.oauthClient!
.client
.post(url,
parameters: parameter,
completionHandler: {result in
switch result{
case .success(let response):
self.translatedText = self.translationController.getTranslatedText(result: response)
case .failure(let error):
print(error.description)
break
}
})
}) {
Text("翻訳")
}.padding()
Text(self.translatedText)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import Foundation
import SwiftyJSON
import OAuthSwift
class TranslationController{
var apiKey = ""
var apiSecret = ""
var apiUserName = ""
var apiBaseUrl = "https://mt-auto-minhon-mlt.ucri.jgn-x.jp"
var oauthClient:OAuth1Swift!
init(apiKey:String?, apiSecret:String?, apiUserName:String?){
if let apiKey = apiKey{
self.apiKey = apiKey
}
if let apiSecret = apiSecret{
self.apiSecret = apiSecret
}
if let apiUserName = apiUserName{
self.apiUserName = apiUserName
}
self.oauthClient = OAuth1Swift(consumerKey: self.apiKey, consumerSecret: self.apiSecret)
}
func generateParameter(fromLang:String, toLang:String, text:String) -> (OAuthSwift.Parameters, String){
var parameter = OAuthSwift.Parameters()
parameter["key"] = self.apiKey
parameter["name"] = self.apiUserName
parameter["type"] = "json"
parameter["text"] = text
return (parameter, "\(self.apiBaseUrl)/api/mt/generalNT_\(fromLang)_\(toLang)/")
}
func getTranslatedText(result:OAuthSwiftResponse) -> String{
guard let resultString = result.string else{
return ""
}
let data = JSON.init(parseJSON: resultString)
if let resultText = data["resultset"]["result"]["text"].string{
return resultText
}
return ""
}
}
コード読んでくださいって感じなんですが、ただ単に、翻訳元のテキストを投げて翻訳結果を取得するってだけですね
APIキー関係は、こちらからご自身で取得してみてください
ハマったところ
NICTのAPIはOAuth1認証です(OAuth2ではありません)
自分でシグネチャを生成するのは面倒だと判断したので、OAuthSwiftを使いましたが、そいつがエラーに
[f:id:beah:20200224204033p:plain]
[f:id:beah:20200224204049p:plain]
iOSだと動くのに、なんでやねんという感じなんですが、(OAuthSwift自体はMac対応を謳っています)sudo gem update cocoapods
でCocoapodsをアップデートして、(念の為)pod install
したら上手く動きました
バージョンの問題なんですかね
というわけで完成
[f:id:beah:20200224204525p:plain]
うん!いい感じですね!(UIが絶望的に下手っぴですが)
まとめ
SwiftUIは、これまでよりは表現が制約されますが、よしなにやってくれるというのがとても強いと思いました
AutoLayout未だに意味分かんねぇもん・・・
後は、ライブラリ関係がMac Catalystに対応してくれるといいんですが、なかなか時間かかるでしょうね・・・
そういう意味では、MacとiOSが同じコードで動く!なんて、あまり夢を見過ぎるべきでないと感じました(どちらかというと、iPadOSとmacOSのペアなんですが、正直iPadOSとiOSの違いが自分にはよくわからない・・・)
ではでは〜
※追記:Storyboardでも、Mac Catalystは使えるみたいです、でも正直使いたくねぇ