Mac Catalyst 書初め

こんにちは 最近になってようやくSwiftUIを触り始めたので、この機会にということで、MacCatalystにも挑戦してみました

すごくざっくり言えば、iOSMacのアプリが同じコードで動くということです 実際触ってみた感想で言えば、夢を見過ぎるべきでないということですかね

というわけで、導入してみましょう

何を作る?

所用でTwitterAPIの申請を作成することになったんですが、その申請って英語なんですよね

英語力が死んだ自分には、書くのはしんどいので(そもそもあれ大して読まれてないって説もありますがどうなんですかね)翻訳ソフトに頼りますが、Google翻訳は信用してないので、NICTAPIを使うことにします そして、あのWebサイト、時間制限があるんですよね(24分間)

かといって、メモとかに残すのもだるいので、ネイティブアプリでAPIを叩く感じにします

プロジェクトの作成

プロジェクトの作成方法としては、iOSと一緒です f:id:beah:20200224202637p:plain

User InterfaceSwiftUIにするのを忘れないであげてください

f:id:beah:20200224202826p:plain

Deploy InfoTargetMacにチェックを入れます

f:id:beah:20200224202933p:plain

メッセージが出るのでEnableをクリックします

プロジェクトのMac対応は以上です

f:id:beah:20200224203048p:plain

Deviceの一覧に、MaciPhone/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キー関係は、こちらからご自身で取得してみてください

ハマったところ

NICTAPIは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に対応してくれるといいんですが、なかなか時間かかるでしょうね・・・

そういう意味では、MaciOSが同じコードで動く!なんて、あまり夢を見過ぎるべきでないと感じました(どちらかというと、iPadOSとmacOSのペアなんですが、正直iPadOSとiOSの違いが自分にはよくわからない・・・)

ではでは〜

※追記:Storyboardでも、Mac Catalystは使えるみたいです、でも正直使いたくねぇ