惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
A
About on SuperTechFans
博客园 - Franky
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Last Week in AI
Last Week in AI
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
G
Google Developers Blog

u3blog

从手动配置到自然语言生成规则:一个 Android AI 工具的重构实录 - u3blog 学习版游戏自制云存档同步的方法探索以及总结 - u3blog 鸿蒙next中web组件和navigation的一个bug以及处理方案 - u3blog Android项目cicd流程总结(使用jenkins) - u3blog Android使用Logger开发App本地日志记录功能 - u3blog 一张启动图引发的思考--探索.9图原理和应用场景 - u3blog 跟我一起玩Paging3 - u3blog Android中使用ASPECTJ进行用户操作路径跟踪与日志搜集 - u3blog 彻底摆脱数据线——远程ADB调试小工具开发过程记录 - u3blog 自己实现一个Android网络图片加载器 - u3blog
ChatGPT是怎么帮我写ios代码的 - u3blog
2024-02-02 · via u3blog

背景

博主只会安卓开发,最近使用chatGPT3.5把一个安卓项目转换成了ios项目并成功运行实现功能

应用的主要功能

这个安卓应用主要是拿来看比赛回放的,有时候太迟的足球比赛不想熬夜,但是又不想被剧透看全场回放,就写了个这个应用,这次讨论的重点并不是应用本身,如果大家有兴趣可以评论区留言,我把应用发出来

应用的主要页面有下面几个,1.登录爱奇艺账号页面,2.球队列表页面,3.播放页面

其中播放页面最复杂,要实现以下几个功能

  1. 根据选择的球队,加载搜索比赛结果页面,并把回放和广告列表隐藏,把比赛列表文字放大
  2. 点击了比赛列表,跳转到播放页面
  3. 等待播放页面加载完成,自动点击全屏元素按钮
  4. 在全屏开始播放之后,加载左右两个快放按钮,长按调用网页上的快速播放元素,松开恢复正常速播放

    开始转换

    文件结构差异

    Android的页面主要由两个部分组成
  5. XML布局文件,决定了页面上有哪些元素,以及如何摆放,实现布局部分
  6. Activity文件,决定了页面上元素的各种行为,实现逻辑部分

但是在ios上,并不是这样,chatgpt告诉我,转换出来的东西是一个继承自UIViewController的类,里面同时包含了上面的两个部分内容

要转换哪些功能

应用主要功能就是操作webview加载页面,然后通过调用js的方法来操作页面上的元素,所以webview的加载和js的加载就是这次转换的重点

问题有两个

  1. 怎么用webview加载内容
  2. 怎么操作webview中的内容

    我和gpt的对话

    由于gpt没法自动合并xml和activity的代码,所以我只有让它先转xml,得到布局的controller内容
    列表页面

比如这个布局


    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".PlayerActivity">
        <FrameLayout
            android:visibility="gone"
            android:id="@+id/mFlVideoContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        <FrameLayout
            android:id="@+id/mFlVideoContainer1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
            <LinearLayout
                android:orientation="horizontal"
                android:id="@+id/ll_container"
                android:layout_marginBottom="50dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <Button
                    android:layout_weight="1"
                    android:layout_width="0dp"
                    android:background="#00000000"
                    android:id="@+id/back_bt"
                    android:layout_height="match_parent"/>
                <Button
                    android:layout_weight="3"
                    android:layout_width="0dp"
                    android:visibility="invisible"
                    android:enabled="false"
                    android:background="#00000000"
                    android:id="@+id/pause_bt"
                    android:layout_height="match_parent"/>
                <Button
                    android:layout_weight="1"
                    android:layout_width="0dp"
                    android:background="#00000000"
                    android:id="@+id/go_bt"
                    android:layout_height="match_parent"/>
            </LinearLayout>
        </FrameLayout>
        <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/webview"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

让它给我转成ios版本,转出来是下面这样的

import UIKit
import WebKit

class PlayerViewController: UIViewController {

    // UIView elements
    let videoContainer: UIView = {
        let view = UIView()
        view.isHidden = true
        return view
    }()

    let videoContainer1: UIView = {
        let view = UIView()
        return view
    }()

    let backButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = UIColor.clear
        return button
    }()

    let pauseButton: UIButton = {
        let button = UIButton()
        button.isHidden = true
        button.isEnabled = false
        button.backgroundColor = UIColor.clear
        return button
    }()

    let goButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = UIColor.clear
        return button
    }()

    let webView: WKWebView = {
        let webView = WKWebView()
        return webView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set up constraints for each element
        videoContainer.translatesAutoresizingMaskIntoConstraints = false
        videoContainer1.translatesAutoresizingMaskIntoConstraints = false
        backButton.translatesAutoresizingMaskIntoConstraints = false
        pauseButton.translatesAutoresizingMaskIntoConstraints = false
        goButton.translatesAutoresizingMaskIntoConstraints = false
        webView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(videoContainer)
        view.addSubview(webView)

        NSLayoutConstraint.activate([
            videoContainer.topAnchor.constraint(equalTo: view.topAnchor),
            videoContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            videoContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            videoContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            videoContainer1.topAnchor.constraint(equalTo: videoContainer.topAnchor),
            videoContainer1.leadingAnchor.constraint(equalTo: videoContainer.leadingAnchor),
            videoContainer1.trailingAnchor.constraint(equalTo: videoContainer.trailingAnchor),
            videoContainer1.bottomAnchor.constraint(equalTo: videoContainer.bottomAnchor),

            backButton.topAnchor.constraint(equalTo: videoContainer.bottomAnchor),
            backButton.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            backButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            backButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.25),

            pauseButton.topAnchor.constraint(equalTo: videoContainer.bottomAnchor),
            pauseButton.leadingAnchor.constraint(equalTo: backButton.trailingAnchor),
            pauseButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            pauseButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),

            goButton.topAnchor.constraint(equalTo: videoContainer.bottomAnchor),
            goButton.leadingAnchor.constraint(equalTo: pauseButton.trailingAnchor),
            goButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            goButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.25),

            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
}

遇到的坑

gpt生成的代码并不是直接可以用的

gpt生成出来的代码看似正确,但是有时候运行就会发现缺少内容,比如有的变量没有定义就使用了,你得追问它,才会告诉你

虽然告诉你了,但是大概率会重新生成一份代码,这又是一个坑,这个重新生成的代码又有概率和第一次完全不同

这坑需要有一定的编程能力,自己阅读下gpt给的代码,才可以实现想要的功能,不然就会被它坑

对于稍微复杂一点的布局,gpt给出的方案并不总能成功实现

由于给出的ios界面是用代码实现的,给出的安卓布局是xml的,有些时候ios并没有安卓的布局控件,gpt给出的方案运行起来就会出现错位等情况,这时候也需要人工调试

对于项目配置方面,gpt并不能给出精准的解答

这点主要体现在其中一个功能上,从ios应用中拉起爱奇异体育并播放,chatgpt给出的方案不管怎么设置都无法实现,因为它理解成了我需要从其他应用跳转到自己的ios应用

其实这个问题在网上一搜就能处理,这也是一个坑,不能全部相信gpt的话

ios和安卓webview的差异导致的功能实现不同

由于爱奇艺的限制,使用ios的wkwebview无法进行播放,在安卓却可以播放,所以需要调整功能,不能直接在应用内播放,需要走scheme的方式跳转爱奇艺app做播放

对于wkwebview无法播放的问题,我问了gpt很久,每次它也非常配合,给出各种各样的方案,花了很多时间,但是都无效

这个问题也需要自己想一想,用自带的浏览器打开一下页面,把agent换成pc端,发现也无法播放,所以确认是wkwebview的问题,而不是实现方案的问题

总结

  • 在使用gpt的时候,也不能无脑相信它,有时候它明明不会或者不懂,也会给出答案,这种答案看起来没问题,其实是错误的,会把方向带偏,需要特别留意

  • 使用gpt可以让我这样一个完全不懂ios的开发人员在短时间内完成简单的开发工作,放在以前我至少需要学习基础的ios开发知识,学习完了之后,我还需要在开发遇到问题的时候一个点一个点的搜,大概率是没有相同问题的,需要自己从各种各样的结果中提炼

  • 现在gpt帮我完成了这个步骤,让这次开发变得轻松了很多

  • gpt对开发人员的帮助确实是非常大,粗略估计,这次的小应用开发,为了节省了60%以上的时间,相信随着技术的发展,这个工具会越来越便利,这次使用的是免费的gpt3.5都如此强大,收费的4.0真是不敢想象