使用chatgpt在Xcode中优化代码:开发的新时代
#编程 #ios #xcode #chatgpt

作为开发人员,您知道编写高效有效的代码对于创建成功的软件至关重要。但是,优化代码可能是一项耗时且具有挑战性的任务。幸运的是,您现在可以使用带有chatgpt的Xcode扩展名来快速,轻松地优化代码。在本文中,我们将向您展示如何创建连接到chatgpt的XCode源编辑器扩展程序,该扩展程序可帮助您立即优化代码。

首先,因为我们目前都知道Chatgpt是一种人工智能聊天机器人,它建在OpenAI的GPT-3.5和大型语言模型(LLMS)的GPT-4家族(LLMS)之上,并经过微调,可用于使用自然语言请求进行应用。

我们必须记住,ChatGpt将不会成为开发人员的替代品,它将帮助我们使用一种工具,以使我们变得更好,并以更少的精力提高开发人员的质量,而人类的歧义将永远不会被AI复制。

因此,现在我们将接近该AI的能力来创建XCode源编辑器扩展程序,以帮助我们以最快的方式优化代码,请记住,请记住Chatgpt提供的解决方案不应将其视为最终解决方案。考虑到这些考虑,我们将直接为创建扩展而跳。

如何包括chatgpt到xcode

首先要做的是在此发布之日之后向OpenAI注册,在此发布之日,OpenAI给您$ 5.00,您需要向API提出请求,在您创建帐户后,请继续进行个人资料以生成API钥匙。

生成您的OpenAI API密钥

  1. 转到位于右上角的个人资料屏幕,然后选择“查看API键”
  2. 然后选择“创建新的秘密密钥” secret api key
  3. 将生成的密钥保留在注释中,因为我们将在片刻之内需要它与OpenAi Rest API
  4. 进行通信

如何创建XCode源编辑器扩展程序

现在,我们已经准备好了所有用于代码优化扩展的东西了,现在该继续详细说明我们的chatgpt扩展程序了。由于Xcode 13的发布以来,创建扩展的方法已经改变了。

  1. 首先,我们需要在XCode内部创建一个新的MacOS应用程序,可以选择SwiftUI或Uikit,以防在这种情况下为扩展创建UI,在这种情况下,我们只专注于扩展名。您可以随时保存它。 create xcode project
  2. 转到您的xcodeproj文件(第一个带有项目名称和蓝色正方形图标的文件)添加新目标,选择Xcode源编辑器扩展程序扩展程序嵌入到项目中并激活。 configuration file xcode extension
  3. 从这里开始,我们准备启动Xcode的Chatgpt扩展名

每当您想尝试扩展名时,请确保在此场合选择正确的方案,称为chatgptextension,然后选择Xcode,然后您可以从“编辑器”选项卡和列表的底部进行测试。<<<<<<<<<<<<<<<<<< /p>

编码您的chatgpt扩展

要开始,我们需要创建类和代码结构来对Chatgpt API进行呼叫,您可以使用我的示例或详细说明课程取决于您。请记住,此代码必须选择扩展目标,而不是主要应用程序。

  • 创建一个与OpenAI相关名称IT OpenAiClient的新组,从这里创建组模型以保持更好的结构。
  • 我们需要的第一个结构将被称为消息,它将是可编码的,因为我们要求两种情况下请求和服务响应。

    struct Message: Codable {
        let role: String
        let content: String
    }
    
  • 然后,我们继续进行ChatCompletionRequest的结构,这是将发送我们要优化的代码的结构,它是可以编码的,因为它只会发送数据并且不希望收到,因此我们将代码保持清洁器保持。

    struct ChatCompletionRequest: Encodable {
        let model: String
        let messages: [Message]
        let maxTokens: Int
    
        private enum CodingKeys: String, CodingKey {
            case model
            case messages
            case maxTokens = "max_tokens"
        }
    }
    
    
  • 现在是时候进行服务的响应了,这将创建ChatCompletionResponse,该ChatCompletionResponse将负责收到代码建议,以通过对我们的代码优化的内容进行说明。

    struct ChatCompletionResponse: Decodable {
        let id: String
        let object: String
        let created: Int
        let model: String
        let usage: Usage
        let choices: [Choice]
    }
    
    struct Usage: Decodable {
        let promptTokens: Int
        let completionTokens: Int
        let totalTokens: Int
    
        private enum CodingKeys: String, CodingKey {
            case promptTokens = "prompt_tokens"
            case completionTokens = "completion_tokens"
            case totalTokens = "total_tokens"
        }
    }
    
    struct Choice: Decodable {
        let message: Message
        let finishReason: String
        let index: Int
    
        private enum CodingKeys: String, CodingKey {
            case message
            case finishReason = "finish_reason"
            case index
        }
    }
    
    

这些结构是从请求和响应主体中直接消耗OpenAI Chat Completion API的。

  • 是时候继续使用OpenAI类使用我们最近创建的模型,开始创建一个新的Swift文件名OpenAI,然后是导入基金会库,我们需要将urlSessions调用到API

Import Foundation

  • 然后出于测试目的声明两个变量endpointapikey,最后我们将确保此数据,以便从我们的项目的PLIST文件中获得

    let endpoint = "https://api.openai.com/v1/chat/completions"
    let apiKey = "<Insert your secret api key here>"
    
  • 继续使用为RESTAPI创建请求的函数,它需要我们引入的prompt作为参数,它必须是一个可以接受并返回urlrequest的Message对象,您可以将其称为私有通过班级访问。

    private func createRequest(prompt: Message) -> URLRequest {    
    }
    
  • 在这种情况下,添加带有所需标头的urlrequest,endpointapikey变量和邮政方法,然后使用提示符创建一个ChatCompletionRequest,该ChatCompletionRequest将被编码为JSON并返回创建的请求。
    在模型中,如果您可以访问它,则可以将其更改为GPT-4。

    private func createRequest(prompt: Message) -> URLRequest {
        var request = URLRequest(url: URL(string: endpoint)!)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
    
        let requestBody = ChatCompletionRequest(model: "gpt-3.5-turbo",
                                         messages: [prompt],
                                         maxTokens: 1000)
    
        let encoder = JSONEncoder()
        do {
            let jsonData = try encoder.encode(requestBody)
            request.httpBody = jsonData
        } catch {
           print(error)
        }
    
        return request
    }
    
  • 对于sendrequest函数,我们将期望@escaping关闭以处理API的响应,请致电createReqeuest函数,然后将所有数据发送给使用dataTask的URLSESSION,此后通过关闭发送获得的数据。

    private func sendRequest(prompt: Message, completion: @escaping (ChatCompletionResponse?, Error?) -> ()) {
        let request = createRequest(prompt: prompt)
        let session = URLSession.shared
    
        let task = session.dataTask(with: request) { (data, response, error) in
            if let error = error {
                completion(nil, error)
                return
            }
    
            guard let httpResponse = response as? HTTPURLResponse else {
                completion(nil, NSError(domain: "OpenAIClientError", code: 0, userInfo: nil))
                return
            }
    
            guard (200...299).contains(httpResponse.statusCode) else {
                completion(nil, NSError(domain: "OpenAIClientError", code: httpResponse.statusCode, userInfo: nil))
                return
            }
    
            guard let data = data else {
                completion(nil, NSError(domain: "OpenAIClientError", code: 0, userInfo: nil))
                return
            }
    
            do {
                let decoder = JSONDecoder()
                let response = try decoder.decode(ChatCompletionResponse.self, from: data)
                completion(response, nil)
            } catch {
                completion(nil, error)
            }
        }
    
        task.resume()
    }
    
  • 现在将创建公共功能以发送提示以进行优化的代码,发送预期提示上下文的方式与仅要求它优化代码一样容易,在演示上,我会显示什么输出。

    func getOptimizedCode(for prompt: String, completionHandler: @escaping (String?) -> Void){
        sendRequest(
            prompt: Message(role: "user", content:"""
    Optimize the following Swift code:
    ```

swift
    \(prompt)


    ```
    """)

        ) { (response, error) in
            guard error == nil else {
                print("There was an error in the OpenAI call.")
                print(error?.localizedDescription ?? "")
                completionHandler(nil)
                return
            }

            if let optimizedCode = response?.choices.first?.message.content{
                let result = "/**\n\(optimizedCode)\n*/"
                completionHandler(result)
            }
        }
    }
  • 这就是Openai类的组成方式,现在我们将继续为扩展程序创建命令

XCode源编辑器命令

Xcode扩展程序中的命令是调用要在我们的源代码中执行的任务或函数的方法,在这种情况下,将是优化我们的代码。
我们可以拥有尽可能多的命令,因为我们希望没有限制,并且每个命令都必须在其特定类中,其中包括协议NSObjectXCSourceEditorCommand

  • 首先将默认类SourceEditorCommand重命名为OptimizeCodeCommand从这里选择我们要优化的所选代码,我选择仅选择的代码以不浪费dockens,而不浪费在类中只有变量的代码确定正在优化什么代码。
  • 在命令类中,我们具有一个具有invocation变量的性能函数,该函数是一个XCSourceEditorCommandInvocation这个对象具有很多函数,但是我们要使用的函数是buffer,它可以帮助我们从源中获得文本,选择不那么容易,似乎我们必须使用下一个功能处理所选行。

    private func extractSelection(_ selections: [XCSourceTextRange], fromText lines: [String]) -> String {
        return selections.compactMap { range in
            (range.start.line...range.end.line).map { lines[$0] }.joined()
        }.joined()
    }
    
  • 现在,我们准备好处理源代码的所选行,将其直接发送给chatgpt并打印我们的源代码的建议代码优化。绩效功能的内部添加下一个代码。

    func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
        guard let selectedTextRanges = invocation.buffer.selections as? [XCSourceTextRange],
              let lines = invocation.buffer.lines as? [String]
        else { return completionHandler(nil) }
    
        let selectedText = extractSelection(selectedTextRanges, fromText: lines)
        OpenAIClient().getOptimizedCode(for: selectedText) { result in
            invocation.buffer.lines.add(result ?? "")
            completionHandler(nil)
        }
    }
    

完成闭合可以帮助我们等待chatgpt函数在执行其他任何操作之前结束,如果您将完成在getOptimizedCode函数之外,则命令最终将在我们单击时尽快到达。

  • 我们现在拥有所有必需的代码在这些定义中,我们可以在其中添加扩展名的每个命令。 plist info
  • XCSourceEditorCommandClassName的更改值从$(PRODUCT_MODULE_NAME).SourceEditorCommand$(PRODUCT_MODULE_NAME).<Command Class Name> Eg。 $(PRODUCT_MODULE_NAME).OptimizeCodeCommand
  • XCSourceEditorCommandIdentifier的更改值从$(PRODUCT_BUNDLE_IDENTIFIER).SourceEditorCommand$(PRODUCT_BUNDLE_IDENTIFIER).<Command Class Name> Eg。 $(PRODUCT_BUNDLE_IDENTIFIER).OptimizeCodeCommand
  • 在这种情况下,XCSourceEditorCommandNameXCSourceEditorCommandName的值更改为您想调用命令的任何内容,我们将命名为Optimize code with chatGPT

现在,扩展名准备执行,并使用要优化的任何代码

尝试一下

演示

此准备后,我们准备好运行一些示例:

在此示例中,我们有一个意大利面代码:

    func calculateTotalPrice(quantity: Int, price: Double, discount: Double) -> Double {
        var finalPrice = 0.0
        if quantity > 0 {
            finalPrice = price * Double(quantity)
            if discount > 0 {
                let discountAmount = finalPrice * discount / 100.0
                finalPrice -= discountAmount
                if finalPrice < 0 {
                    finalPrice = 0
                }
            }
        }
        return finalPrice
    }

此代码的问题是嵌套是否复杂的嵌套数量,使代码增加了复杂性。

现在,我们继续运行我们的应用程序扩展名,我创建了一个新的Swift文件,以添加此功能,选择代码后,我们转到编辑器选项卡并选择我们的扩展名称。
example of spaghetti code
选择要优化的代码后,我们选择要运行的命令。
selecting code
完成后,它将出现在您要编辑的文件的末尾。
result of xcode extension

保护您的API键和端点

保护我们的apikey或任何敏感信息的一种非常好的方法,我们可以使用内部PLIST信息添加为字典内的键值,然后我们会这样。

private var apiKey: String {
  get {
    // 1
    guard let filePath = Bundle.main.path(forResource: "Info", ofType: "plist") else {
      fatalError("Couldn't find file 'Info.plist'.")
    }
    // 2
    let plist = NSDictionary(contentsOfFile: filePath)
    guard let value = plist?.object(forKey: "API_KEY") as? String else {
      fatalError("Couldn't find key 'API_KEY' in 'Info.plist'.")
    }
    return value
  }
}

结论

chatgpt不仅是任何一般用途,目前以及将来的任何时刻,我都认为它不会为开发人员带走工作,而且可以用作加强功能因为在这种情况下可以用于代码优化,所以它仍然需要进一步的分析和测试,以检查建议的代码是否正常工作,并且如果提出的代码优化有效,AI将是一个辅助工具,而不是无辅助的确定性工作机器,则仍然需要监督,不要完全依赖它,而是将其作为一种新的工作工具。

有用的链接

Creating an Xcode Source Editor Extension

OpenAI Platform

How ChatGPT works?