Boost iOS Productivity: Building an AIGC-Powered Xcode Plugin with Swift
This article details how to create iTaTools, a macOS app and Xcode Source Editor Extension that integrates ChatGPT via AIGC to generate code, UI, and documentation directly in Xcode, complete with implementation steps, Swift code samples, and plugin architecture.
Background
Repetitive development tasks reduce efficiency. To streamline interaction with ChatGPT, the team built iTaTools , a macOS application and Xcode source‑editor extension that embed AIGC capabilities directly into the development workflow.
Mac AIGC Tool (iTaTools)
iTaTools is a standalone macOS app written in Swift/SwiftUI. It provides three tabs:
ChatGPT query – send prompts and receive text answers.
Text‑to‑image generation.
A curated list of useful AIGC tools and tips.
Xcode Source Editor Extension
The extension adds four shortcut‑triggered commands that communicate with the ChatGPT API and insert results directly into the editor.
Commands
Generate code from the currently selected text.
Convert JSON mock data into Swift model classes.
Insert Apple‑style documentation comments for the selected code block.
Provide a plain‑language explanation of the selected snippet.
Implementation Details
AIGC API Usage
The project uses the official ChatGPT (OpenAI) API. Developers must adapt request headers and payloads to the provider’s documentation.
Request Headers (Swift)
extension NTESNeteaseAIService {
/// Create signed request headers for the AIGC service
/// - Parameters: appId and appKey obtained from the developer console
public func signedHeaders(appId: String, appKey: String) -> [String: String] {
let nonce = String((0..<10).map { _ in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".randomElement()! })
let timestamp = String(Int64(Date().timeIntervalSince1970))
let str2Sign = "appId=\(appId)&nonce=\(nonce)×tamp=\(timestamp)&appkey=\(appKey)"
let sign = Insecure.MD5.hash(data: str2Sign.data(using: .utf8)!).map { String(format: "%02hhx", $0) }.joined().uppercased()
return ["appId": appId, "nonce": nonce, "timestamp": timestamp, "sign": sign, "version": "v2"]
}
}Prompt Construction
struct NTESNeteaseAIJson2CodeRequestParams: Encodable {
let model = "gpt-3.5-turbo"
let messages: [NTESNeteaseAIChatResponse.Message]
init(promptString: String) {
let finalPrompt = "You are a senior iOS developer. Convert the following JSON to a Swift class prefixed with NTESNB, include an init method, and provide a static demo variable \(promptString)."
let message = NTESNeteaseAIChatResponse.Message(role: "user", content: finalPrompt, name: "Jerry", functionCall: nil)
self.messages = [message]
}
}Response Parsing
struct NTESNeteaseAIChatResponse: Decodable {
let status: String
let desc: String?
let traceId: String?
let detail: Detail?
struct Detail: Decodable {
let id: String?
let object: String?
let created: TimeInterval?
let choices: [Choice]?
let usage: Usage?
}
struct Choice: Decodable { let index: Int?; let finishReason: String?; let message: Message? }
struct Message: Decodable, Encodable { let role: String?; let content: String?; let name: String?; let functionCall: FunctionCall? }
struct Usage: Decodable { let promptTokens: Int?; let completionTokens: Int?; let totalTokens: Int? }
struct FunctionCall: Decodable, Encodable { let name: String?; let description: String?; let parameters: String? }
}Xcode Plugin Development
The plugin is built as an Xcode Source Editor Extension . The main development steps are:
Create a new target:
File → New → Target → macOS → Source Editor Extension.
Implement the required classes:
XCSrouceEditorExtension : Entry point for the extension.
XCSourceEditorCommand : One subclass per AIGC command (e.g., Json2Code, AddComments).
XCSourceTextBuffer : Represents the source file being edited.
XCSourceEditorCommandInvocation : Provides access to the buffer and allows modifications.
Accessing Highlighted Code
let range = self.buffer.selections.firstObject as? XCSourceTextRange
let startLine = range?.start.line ?? 0
let startColumn = range?.start.column ?? 0
let endLine = range?.end.line ?? 0
let endColumn = range?.end.column ?? 0
let startString = String(mouseLineText.dropFirst(startColumn))
var resultString = startString
for i in startLine...endLine {
let line = lines[i]
if i == endLine {
let cut = String(line.prefix(endColumn + 1))
resultString += cut
} else {
resultString += line
}
}
// resultString is sent as the prompt to ChatGPTJson2Code Command Implementation
func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
let source = invocation.buffer.completeBuffer
Task {
do {
let suggestion = try await self.openAIService.json2Code(content: source)
let message = suggestion.detail?.choices?.first?.message?.content ?? "Unable to generate code"
let output = "
\(message)
"
invocation.buffer.lines.removeAllObjects()
invocation.buffer.lines.add(output)
completionHandler(nil)
} catch {
completionHandler(error)
}
}
}Info.plist Configuration
The extension’s Info.plist must list each command dictionary with a display name, the implementing class, and a unique identifier. This enables the commands to appear in Xcode’s Editor menu and be bound to shortcuts.
iOS UI Code Generation Example
Using a custom prompt that encodes the team’s UI conventions (Objective‑C/Swift, SnapKit/Masonry layout, Get‑style UI creation, unified dark/light mode), the tool can generate ready‑to‑use UI code. Below is a generated Objective‑C example.
// NTESNBLoginHeader.h
#import <UIKit/UIKit.h>
@interface NTESNBLoginHeader : UIView
@property (nonatomic, strong) UILabel *username;
@property (nonatomic, strong) UILabel *password;
@property (nonatomic, strong) UIImageView *avatar;
- (void)updateUsername:(NSString *)username;
- (void)updatePassword:(NSString *)password;
- (void)updateAvatar:(UIImage *)avatar;
@end
// NTESNBLoginHeader.m
#import "NTESNBLoginHeader.h"
#import <Masonry/Masonry.h>
@implementation NTESNBLoginHeader
- (instancetype)init {
self = [super init];
if (self) {
[self addSubview:self.username];
[self addSubview:self.password];
[self addSubview:self.avatar];
[self setupLayout];
}
return self;
}
- (void)setupLayout {
[self.avatar mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(20);
make.centerX.equalTo(self);
make.size.mas_equalTo(CGSizeMake(50, 50));
}];
[self.username mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.avatar.mas_bottom).offset(10);
make.left.right.equalTo(self);
}];
[self.password mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.username.mas_bottom).offset(10);
make.left.right.equalTo(self);
}];
}
- (void)updateUsername:(NSString *)username { self.username.text = username; }
- (void)updatePassword:(NSString *)password { self.password.text = password; }
- (void)updateAvatar:(UIImage *)avatar { self.avatar.image = avatar; }
@endConclusion
Embedding ChatGPT‑based AIGC tools into the IDE eliminates manual copy‑paste cycles and accelerates repetitive, low‑complexity coding tasks. The iTaTools macOS app and Xcode source‑editor extension demonstrate a practical workflow for code generation, model conversion, documentation insertion, and code explanation. Future work may include training local models to better align with team‑specific coding standards and private libraries.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
