[Swift / Kotlin] ChatGPTでやりたいことをお願いすると良い感じにソースコードが返ってくるので、もう我々は要らないのでは? と思わされた話

2023.02.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

CX事業本部の中安です。まいどです。

最近トレンドなキーワードといえば「ChatGPT」だと思いますが、ChatGPTでは実現したいことを「ソースコードで出力して」とお願いすると綺麗なソースコード例を出してくれます。

「そんなことまでできるんだー」とビックリしたので、今回は主にSwift(またはKotlin)で実現したいことをいくつかChatGPTにお願いしてみて、どんなソースコードを出してくれるのかを試してみました。

やってみた

お願いごとのフォーマットは基本的に

「(言語名)で (やりたいこと) するソースコードを出力して」

と書くだけです。

「POSTリクエストするソースコードを出力して」

ソースコードを要求するとこのような感じで出力してくれます。 Swift用にシンタックスハイライトされてるとはいえませんが、コードをコピーする機能もついていて親切UIですね。

では実際にどのように出力されたかというと

SwiftでPOSTリクエストを送信するには、URLSessionを使用することができます。次のコードは、POSTリクエストを送信するためのSwiftの例です。

let url = URL(string: "https://www.example.com/api/create")!
var request = URLRequest(url: url)
request.httpMethod = "POST"

let parameters: [String: Any] = [
    "name": "John Doe",
    "email": "johndoe@example.com",
    "message": "Hello, World!"
]

request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else {
        print("Error: \(error)")
        return
    }
    
    let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
    if let responseJSON = responseJSON as? [String: Any] {
        print(responseJSON)
    }
}

task.resume()

このコードは、名前、メールアドレス、メッセージのパラメータを持つPOSTリクエストを送信します。リクエストが成功すると、サーバーからのレスポンスをJSONオブジェクトとして受け取り、コンソールに出力することができます。

特にライブラリを使用せず、URLSessionを用いたシンプルな例が返ってきました。

さくっと試しにAPIにPOSTで送信してみたいなーというときには、これをコピペして必要箇所を直せばそのまま使うことができるでしょう。

同じことをAndroidでもやりたいなーと思った時にも便利だと思います。 iOSとAndroidで同じことがやりたくても実装方法が違う場合もありますからね。

Kotlin(Android)でPOSTリクエストするソースコードを出力して

KotlinでAndroidアプリからPOSTリクエストを送信するには、Volleyライブラリを使用することができます。次のコードは、POSTリクエストを送信するためのKotlinの例です。

val queue = Volley.newRequestQueue(this)
val url = "https://your-api-url.com/api/create_user"

val params = HashMap<String, String>()
params["name"] = "John Doe"
params["email"] = "johndoe@example.com"

val jsonObject = JSONObject(params)

val request = JsonObjectRequest(
    Request.Method.POST, url, jsonObject,
    Response.Listener { response ->
        Log.d("Response", response.toString())
    },
    Response.ErrorListener { error ->
        Log.e("Error", error.toString())
    }
)

queue.add(request)

このコードは、Volleyライブラリを使用してPOSTリクエストを送信するものです。リクエストパラメータを含むJSONObjectを作成し、JsonObjectRequestオブジェクトを作成してリクエストを送信します。成功時はレスポンスを出力し、失敗時はエラーを出力します。

なるほど、Androidでは「Volleyライブラリ」を使用するんだなーということが分かります。

「1秒ごとにカウントダウンをするソースコードを出力して」

Swiftで1秒ごとにカウントダウンをするソースコードを出力して

var count = 10
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
    count -= 1
    print(count)
    
    if count == 0 {
        timer.invalidate()
    }
}

このコードは、scheduledTimerメソッドを使用して、1秒ごとに繰り返されるTimerを作成します。Timerのイベントハンドラー内では、カウント変数をデクリメントし、各イベントにおいて値を出力します。カウントが0になった場合は、Timerを無効にすることで、カウントダウンを停止させます。

scheduledTimerを使用するだけではなく、最後にinvalidateをすることも解説されててよいですね。

Androidだとどうやって実装するのでしょう?

Kotlin(Android)で1秒ごとにカウントダウンをするソースコードを出力して

Kotlin(Android)で1秒ごとにカウントダウンするには、HandlerクラスとRunnableインターフェイスを使用することができます。次のコードは、1秒ごとにカウントダウンするためのKotlin(Android)の例です。

var count = 10
val handler = Handler()
val runnable = object : Runnable {
    override fun run() {
        count--
        Log.d("Countdown", count.toString())
        
        if (count > 0) {
            handler.postDelayed(this, 1000)
        }
    }
}

handler.post(runnable)

このコードは、HandlerクラスとRunnableインターフェイスを使用して、1秒ごとにカウントダウンする処理を実現します。Runnableオブジェクト内では、カウント変数をデクリメントし、各イベントにおいて値をログ出力します。カウントが0より大きい場合は、HandlerのpostDelayedメソッドを使用して再帰的に実行させます。

「HandlerのpostDelayedメソッドを使用して再帰的に実行」と、遅延を再帰的にさせることでタイマー処理をしていることも解説してくれます。 ソースコードだけを出すのではなく、ちゃんとどういう意図のソースコードなのかを書いてるところもすごいところです。

「端末内の画像を選択させるソースコードを出力して」

最後はアプリではよくあるユーザが所持する画像から選択させるUIの実装方法です。

Swiftで端末内の画像を選択させるソースコードを出力して

Swiftで端末内の画像を選択させるには、UIImagePickerControllerクラスを使用することができます。次のコードは、端末内の画像を選択させるためのSwiftの例です。

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBAction func selectImage(_ sender: Any) {
        let imagePickerController = UIImagePickerController()
        imagePickerController.delegate = self
        imagePickerController.sourceType = .photoLibrary
        present(imagePickerController, animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let selectedImage = info[.originalImage] as? UIImage {
            // Do something with the selected image
        }
        dismiss(animated: true, completion: nil)
    }
}

このコードは、UIImagePickerControllerクラスを使用して、端末内の画像を選択させる処理を実現します。画像選択ボタンがタップされた際に、画像選択コントローラを表示します。選択された画像は、didFinishPickingMediaWithInfoデリゲートメソッド内で取得することができます。

UIImagePickerControllerを使った無駄のないシンプルなソースコードですね。 すごいなぁー

Kotlin(Android)で端末内の画像を選択させるソースコードを出力して

Kotlin(Android)で端末内の画像を選択させるには、Intentクラスを使用することができます。次のコードは、端末内の画像を選択させるためのKotlin(Android)の例です。

import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.provider.MediaStore
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private val REQUEST_IMAGE_CAPTURE = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        select_image_button.setOnClickListener {
            dispatchTakePictureIntent()
        }
    }

    private fun dispatchTakePictureIntent() {
        Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).also { takePictureIntent ->
            takePictureIntent.resolveActivity(packageManager)?.also {
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
            val selectedImage = data?.data
            selectedImage?.let {
                Log.d("SelectedImage", selectedImage.toString())
                // Do something with the selected image
            }
        }
    }
}

このコードは、Intentクラスを使用して、端末内の画像を選択させる処理を実現します。画像選択ボタンがタップされた際に、画像選択Intentを発行します。選択された画像は、onActivityResultメソッド内で取得することができます。

OSの違いによりかなり実装方法が違うことがシンプルに分かりますね。

おわりに

実は、この記事を書こうとしたときは「ChatGPTが出力したソースコードをコードレビューしてみた」的な記事にしようと思ったのですが、 出力されてくるソースコードがここまで書いたとおり簡潔かつ分かりやすかったので、単純にすごいなーという感想を述べる記事になってしまいました(笑)

簡単な関数をつくるときには、いろいろとググらずにChatGPTさんに聞いてしまった方がもはや早いのかもしれません。

エンジニアが実装方法にうーんと悩まない時代ももうすぐ訪れそうな予感がしますね。

もちろん、何も考えずコピペしたりせず、ソースコードの意図をちゃんと読み取るのことは引き続き大事だと思いますが。

ちなみに、同様のブログとして若槻さんのブログもご紹介しておきます。

ChatGPTにテストコード(Jest)を渡すだけでAmazon DynamoDBにクエリをするコードを書いてもらえました
https://dev.classmethod.jp/articles/chatgpt-write-aws-sdk-code/

こちらはテストコードを直接投げて回答をもらってるので、さらにすごいなーと思いました。

ではまたー。