Prompt 6: iOS'da AI — Apple Foundation Models, Xcode agentlari va On-Device ML
🤖 Prompt & AI Engineering
Prompt 6: iOS'da AI — Apple Foundation Models, Xcode agentlari va On-Device ML
Holat: 2026-yil sentabr (Xcode 26.x, iOS 26.x; iOS 27 2026-09-14 da chiqdi). Bu dars ikki yo'nalishni qamraydi: (A) AI yordamida ilova yozish, (B) ilova ichiga AI qo'shish. Kod misollari iOS 26.5 SDK bilan Swift 6 rejimida kompilyatsiya qilib tekshirilgan.
Mundarija
- A. Xcode'dagi agentic coding
- A. MCP: Xcode'ni tashqi agentlarga ulash
- A. CLAUDE.md / AGENTS.md — loyiha qo'llanmasi
- A. AI yozgan kodni tekshirish
- B. Foundation Models: qurilma ichidagi model
- [B. Guided generation:
@Generableva@Guide](#generable) - B. Tool'lar va streaming
- B. 4096 token: context oynasini boshqarish
- B. Bulutdagi LLM: API kalitni ilovaga qo'ymang
- App Review: 5.1.2(i) va maxfiylik
- iOS 27'da nima yangi?
- Xulosa
- Manbalar
1. A. Xcode'dagi agentic coding {#xcode-agents}
- Xcode 26 — coding intelligence: Xcode ichida AI suhbati va kod takliflari. ChatGPT'ni, boshqa provayderlarni yoki lokal model serverini (Ollama, LM Studio) ulash mumkin.
- Xcode 26.3 (Apple e'loni: 2026-02-03) — to'liq agentic coding. Anthropic'ning Claude Agent va OpenAI'ning Codex agentlari Xcode ichida vazifani bo'laklaydi, fayllarni o'qiydi va o'zgartiradi, build qiladi, Preview orqali natijani tekshiradi. Xcode o'z imkoniyatlarini MCP (Model Context Protocol) orqali ham ochdi. Manba: Apple Newsroom.
Qachon nima ishlatiladi?
| Vazifa | Vosita |
|---|---|
| Bitta funksiyani tushuntirish, kichik tuzatish | Xcode ichidagi AI suhbati |
| Ko'p faylli refactor, migratsiya, test yozish | Agent (Claude Agent / Codex, Xcode ichida yoki terminalda) |
| Build/test/simulator'ni agentga boshqartirish | MCP (2-bo'lim) |
2. A. MCP: Xcode'ni tashqi agentlarga ulash {#mcp}
Xcode 26.3+ bilan birga mcpbridge dasturi keladi. U terminaldagi agentlar va Xcode'ning MCP tool'lari o'rtasida STDIO ko'prigi vazifasini bajaradi. Buni o'z kompyuteringizda tekshirishingiz mumkin (Xcode 26.5 dagi haqiqiy chiqish):
$ xcrun mcpbridge --help
mcpbridge - STDIO Bridge for Xcode MCP Tools
USAGE:
xcrun mcpbridge
xcrun mcpbridge run-agent <agent-name> [agent-args...]
...
DESCRIPTION:
Without a subcommand, acts as a STDIO bridge between MCP (Model Context
Protocol) clients and Xcode's MCP tool service. Reads JSON-RPC 2.0
messages from stdin and forwards responses to stdout.
Claude Code'ga ulash:
claude mcp add --transport stdio xcode -- xcrun mcpbridge
Endi terminaldagi agent ishlab turgan Xcode orqali loyihani build qilishi, testlarni ishga tushirishi va hujjatlarni qidirishi mumkin. Xcode ochiq bo'lishi kerak.
Hamjamiyatda XcodeBuildMCP (Sentry tomonidan ochiq manba) ham mashhur. U Xcode'ni ochmasdan build, test, simulator va qurilma bilan ishlaydi (mobilebuildmcp.com). Tool'lar soni versiyadan versiyaga o'zgaradi — joriy ro'yxatni saytidan ko'ring.
3. A. CLAUDE.md / AGENTS.md — loyiha qo'llanmasi {#agents-md}
Agent har sessiyani loyihani bilmasdan boshlaydi. Loyiha ildizidagi qo'llanma fayli bu bo'shliqni to'ldiradi:
- **
CLAUDE.md** — Claude Code o'qiydi. - **
AGENTS.md— ko'plab agentlar (Codex, Copilot, Cursor, Gemini CLI va boshqalar) uchun umumiy format. 2025-12-09 da OpenAI va Anthropic uni Linux Foundation'ga topshirib, Agentic AI Foundation**ni tashkil qilishdi (OpenAI).
iOS repo uchun qo'llanma quyidagi savollarga javob bersin:
# CLAUDE.md — MyApp (iOS)
## Build & test
- Xcode 26.4, Swift 6 language mode, minimal target iOS 17.
- Test: xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17'
## UI
- Yangi ekranlar — SwiftUI. Eski UIKit ekranlariga faqat bug-fix.
- Ranglar va shriftlar faqat DesignSystem paketidan.
## Architecture
- MVVM: View'da biznes mantiq yo'q. ViewModel'lar @MainActor @Observable.
- Tarmoq — NetworkClient (async/await). Completion handler yozilmaydi.
## Project file
- Yangi kodni iloji boricha Packages/ ichidagi Swift Package'larga yoz.
- project.pbxproj ni qo'lda tahrirlama.
## Qat'iy qoidalar
- Force unwrap (!) yo'q, try! yo'q.
- Secret'lar (API kalit) kodda yo'q — faqat .xcconfig (gitignore'da) orqali.
project.pbxproj haqidagi qoida muhim. Bu fayl mo'rt: agent uni noto'g'ri tahrirlasa, loyiha ochilmay qolishi mumkin. Mantiqni Swift Package'larga ajratsangiz, agent faqat .swift fayllar bilan ishlaydi.
4. A. AI yozgan kodni tekshirish {#review}
AI kodi kompilyatsiya bo'lishi uning to'g'riligini anglatmaydi. Review'da quyidagilarni tekshiring:
- Mavjud bo'lmagan yoki eskirgan API. Model eski Swift/iOS versiyalaridagi yoki umuman yo'q metodni ishlatishi mumkin. Ayniqsa yangi framework'larda (Foundation Models kabi).
- **Force unwrap (
!) vatry!** — "kompilyatsiya bo'ladigan eng qisqa yo'l", production'da crash manbai. - Concurrency:
@unchecked Sendableyokinonisolated(unsafe)bilan "o'chirib qo'yilgan" ogohlantirishlar. Swift 6 kompilyatori data race'larning ko'pini ushlaydi — uni yolg'on bilan tinchitmang. - Testlar nimani tekshiradi? Test haqiqiy xatti-harakatni tekshiryaptimi yoki faqat mock'ni takrorlayaptimi?
- Maxfiylik: consumer rejalarda (Free/Pro/Max) sozlama yoqilgan bo'lsa, suhbatlar modelni o'qitishda ishlatilishi mumkin. Commercial shartlarda (API, Team/Enterprise) Anthropic kodingiz bilan model o'qitmaydi (Claude Code — data usage). Kompaniya kodini qaysi rejada yuborayotganingizni biling.
.envva kalitlarni hech qachon yubormang.
5. B. Foundation Models: qurilma ichidagi model {#foundation-models}
Foundation Models framework (iOS 26, iPadOS 26, macOS 26, visionOS 26) — Apple Intelligence'ni harakatga keltiradigan qurilma ichidagi (on-device) katta til modeliga Swift API.
- Internet kerak emas, so'rov uchun to'lov yo'q, ma'lumot qurilmadan chiqmaydi.
- Faqat Apple Intelligence qo'llab-quvvatlanadigan qurilmalarda ishlaydi (iPhone 15 Pro va undan yangi, M1+ iPad va Mac). Foydalanuvchi uni Settings'da yoqqan bo'lishi kerak.
Shuning uchun har doim avval mavjudligini tekshiring (holatlar SDK'dagi SystemLanguageModel.Availabilitydan olingan):
import FoundationModels
func aiStatusText() -> String {
switch SystemLanguageModel.default.availability {
case .available:
return "AI tayyor"
case .unavailable(.deviceNotEligible):
return "Bu qurilma Apple Intelligence'ni qo'llab-quvvatlamaydi"
case .unavailable(.appleIntelligenceNotEnabled):
return "Settings'da Apple Intelligence'ni yoqing"
case .unavailable(.modelNotReady):
return "Model yuklanmoqda, birozdan keyin urinib ko'ring"
case .unavailable(_):
return "AI hozircha mavjud emas"
}
}
Simulator'da ham, eski qurilmada ham .available kelmasligi mumkin. UI'da doim zaxira (fallback) holat bo'lsin.
Session — suhbat konteksti. Instructions — sizning (dasturchining) doimiy ko'rsatmangiz, prompt — foydalanuvchi so'rovi:
import FoundationModels
func summarize(lessonText: String) async throws -> String {
let session = LanguageModelSession {
"Sen iOS darslari uchun qisqa xulosa yozuvchi yordamchisan."
"Javobni o'zbek tilida, 3 ta qisqa punkt bilan yoz."
}
let response = try await session.respond(to: "Shu dars matnini xulosala:\n\(lessonText)")
return response.content
}
Xavfsizlik qoidasi (Apple): instructions faqat sizdan kelsin. Foydalanuvchi kiritgan yoki tashqaridan olingan matnni instructions ichiga qo'shmang. U prompt ichida, ma'lumot sifatida tursin.
6. B. Guided generation: @Generable va @Guide {#generable}
JSON so'rab, keyin parse qilish o'rniga, Swift tipini to'g'ridan-to'g'ri so'raysiz. @Generable makrosi model uchun schema yaratadi. @Guide esa har bir maydonga cheklov qo'yadi (constrained decoding):
import FoundationModels
@Generable
struct LessonQuiz {
@Guide(description: "Savol matni, o'zbek tilida")
let question: String
@Guide(.count(4))
let choices: [String]
@Guide(.range(0...3))
let correctIndex: Int
@Guide(.anyOf(["oson", "o'rta", "qiyin"]))
let level: String
}
func makeQuiz(topic: String) async throws -> LessonQuiz {
let session = LanguageModelSession {
"Sen iOS kursi uchun test savollari tuzasan."
}
let response = try await session.respond(
to: "\(topic) bo'yicha bitta savol tuz",
generating: LessonQuiz.self,
options: GenerationOptions(temperature: 0.3)
)
return response.content
}
SDK'dagi guide turlari: string uchun .anyOf([...]), .constant(...), .pattern(regex); sonlar uchun .minimum, .maximum, .range; massiv uchun .count, .minimumCount, .maximumCount.
Tartib muhim: model maydonlarni yuqoridan pastga, ketma-ket yaratadi. Bog'liq maydonni manbasidan keyin qo'ying. Masalan, question → choices → correctIndex: to'g'ri javob indeksi variantlar yozilgandan keyin tanlanadi.
7. B. Tool'lar va streaming {#fm-tools}
Model o'z bilimidan tashqari ma'lumotga muhtoj bo'lsa (masalan, sizning dars katalogingiz), unga tool berasiz. Tool — Tool protokolini bajaradigan tip: nom, tavsif, @Generable argumentlar va call:
import FoundationModels
struct LessonLookupTool: Tool {
let name = "findLesson"
let description = "Kurs katalogidan mavzu bo'yicha darsni topadi va uning slug'ini qaytaradi."
@Generable
struct Arguments {
@Guide(description: "Mavzu, masalan: retain cycle")
let topic: String
}
func call(arguments: Arguments) async throws -> String {
// Haqiqiy ilovada: lokal indeks yoki bazadan qidirish
"retain cycle -> /ios-lessons/uikit-memory"
}
}
func askWithTools(_ question: String) async throws -> String {
let session = LanguageModelSession(tools: [LessonLookupTool()]) {
"Foydalanuvchiga darslarni topishda yordam ber. Kerak bo'lsa findLesson tool'idan foydalan."
}
return try await session.respond(to: question).content
}
Streaming — javobni bo'lak-bo'lak ko'rsatish. @Generable tip bilan har bir "snapshot"da hali to'lmagan maydonlar nil bo'ladi:
import FoundationModels
@Generable
struct Tip {
let title: String
let body: String
}
func streamTip() async throws {
let session = LanguageModelSession()
let stream = session.streamResponse(to: "Swift Concurrency bo'yicha bitta maslahat", generating: Tip.self)
for try await snapshot in stream {
// snapshot.content — Tip.PartiallyGenerated: maydonlar asta-sekin to'ladi
print(snapshot.content.title ?? "…")
}
}
8. B. 4096 token: context oynasini boshqarish {#context-window}
Qurilma ichidagi modelning context oynasi kichik: Apple'ning TN3193 hujjatiga ko'ra 4096 token. Instructions, tool tavsiflari, butun suhbat tarixi va javob shunga sig'ishi kerak (TN3193).
- Oyna to'lsa,
LanguageModelSession.GenerationError.exceededContextWindowSizexatosi keladi. Yangi session ochib, kerakli qismini (masalan, qisqa xulosani) o'tkazasiz. - Raqamni kodda qattiq yozmang. SDK'da
SystemLanguageModel.default.contextSizebor (iOS 26.0+ uchun back-deployed). Token hisoblash uchun iOS 26.4+ datokenCount(for:)qo'shilgan:
import FoundationModels
func logContextBudget() async {
let model = SystemLanguageModel.default
print("Context oynasi: \(model.contextSize) token")
if #available(iOS 26.4, *) {
do {
let used = try await model.tokenCount(for: Instructions("Qisqa va aniq javob ber."))
print("Instructions: \(used) token")
} catch {
print("Token hisoblab bo'lmadi: \(error)")
}
}
}
func isContextFull(_ error: Error) -> Bool {
if case LanguageModelSession.GenerationError.exceededContextWindowSize = error {
return true
}
return false
}
Strategiyalar: eski xabarlarni tashlab yuborish (sliding window), to'lishga yaqin qolganda alohida session bilan tarixni qisqartirish, katta hujjatni tool orqali bo'laklab berish.
9. B. Bulutdagi LLM: API kalitni ilovaga qo'ymang {#cloud}
Qurilmadagi model yetmasa (murakkab fikrlash, uzun hujjat), bulutdagi modelga murojaat qilasiz. Asosiy qoida: API kalit ilova ichida bo'lmasin. IPA faylidan kalitni chiqarib olish oson. Kalit sizib chiqsa, uning hisobiga boshqalar so'rov yuboradi.
To'g'ri arxitektura:
iOS ilova ──(foydalanuvchi tokeni)──► Sizning backend (proxy) ──(API kalit)──► LLM provayder
▲ │ rate limit, log, narx nazorati
└──────────── SSE stream ────────────────┘
Backend (Node.js, rasmiy @anthropic-ai/sdk) — javobni SSE orqali oqim bilan uzatadi:
import express from "express";
import Anthropic from "@anthropic-ai/sdk";
const app = express();
app.use(express.json({ limit: "32kb" }));
const client = new Anthropic(); // ANTHROPIC_API_KEY faqat serverning env'ida
app.post("/chat", async (req, res) => {
const question = String(req.body?.question ?? "").slice(0, 4000);
if (!question) return res.status(400).json({ error: "question required" });
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
try {
const stream = client.messages.stream({
model: "claude-opus-5",
max_tokens: 2048,
messages: [{ role: "user", content: question }],
});
for await (const event of stream) {
if (
event.type === "content_block_delta" &&
event.delta.type === "text_delta"
) {
res.write(`data: ${JSON.stringify({ delta: event.delta.text })}\n\n`);
}
}
res.write("data: [DONE]\n\n");
} catch (error) {
res.write(`data: ${JSON.stringify({ error: "upstream_failed" })}\n\n`);
} finally {
res.end();
}
});
app.listen(3000);
iOS tomoni — URLSession.bytes bilan SSE'ni o'qish:
import Foundation
struct ChatChunk: Decodable, Sendable {
let delta: String
}
enum ChatError: Error {
case badStatus(Int)
}
func streamAnswer(question: String, onToken: @MainActor (String) -> Void) async throws {
var request = URLRequest(url: URL(string: "https://api.example.uz/chat")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("text/event-stream", forHTTPHeaderField: "Accept")
request.httpBody = try JSONEncoder().encode(["question": question])
let (bytes, response) = try await URLSession.shared.bytes(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
guard status == 200 else { throw ChatError.badStatus(status) }
for try await line in bytes.lines {
guard line.hasPrefix("data: ") else { continue }
let payload = line.dropFirst(6)
if payload == "[DONE]" { break }
if let chunk = try? JSONDecoder().decode(ChatChunk.self, from: Data(payload.utf8)) {
await onToken(chunk.delta)
}
}
}
Production uchun qo'shimchalar: foydalanuvchi bo'yicha kunlik limit (backend'da), autentifikatsiya (proxy hammaga ochiq bo'lmasin), timeout va qayta urinish, narxni log qilish.
10. App Review: 5.1.2(i) va maxfiylik {#app-review}
2025-yil 13-noyabrdan App Review Guidelines'ning 5.1.2(i) bandi foydalanuvchining shaxsiy ma'lumotini uchinchi tomon AIga (OpenAI, Anthropic, Google va boshqalar) yuborishdan oldin quyidagilarni talab qiladi:
- qayerga yuborilishini aniq oshkor qilish;
- nima uchun ishlatilishini aytish;
- birinchi yuborishdan oldin aniq ruxsat (explicit permission) olish.
Qurilma ichidagi model (Foundation Models) bu qoidani ishga tushirmaydi — ma'lumot qurilmadan chiqmaydi. Manba: Apple Developer News.
11. iOS 27'da nima yangi? {#ios27}
WWDC26'da (2026-yil iyun) Foundation Models uchun yangi imkoniyatlar e'lon qilindi. Ular iOS 27 SDK (Xcode 27) talab qiladi, shuning uchun bu yerda kompilyatsiya qilib tekshirilmagan. Tafsilotlarni rasmiy sessiyadan o'qing:
- **
LanguageModel/LanguageModelExecutorprotokollari** —LanguageModelSessionga faqat Apple modelini emas, boshqa provayderlarni ham ulash imkoniyati (WWDC26 session 339). - Core AI — Core ML'ning vorisi sifatida taqdim etilgan, qurilma ichida katta modellarni ishga tushirish uchun framework (Xcode 27 bilan keladi).
12. Xulosa {#xulosa}
- Xcode 26.3+ da Claude Agent va Codex Xcode ichida ishlaydi.
xcrun mcpbridgeorqali Xcode'ni terminal agentlariga ham ulash mumkin. CLAUDE.md/AGENTS.md— agentning "yangi xodimga qo'llanma"si: build buyruqlari, arxitektura, qat'iy qoidalar.- AI kodini review qiling: eskirgan API, force unwrap, yashirilgan concurrency muammolari.
- Foundation Models: avval
availability, keyin session.@Generablebilan tipli javob,Toolbilan tashqi ma'lumot. Context oynasi — 4096 token. - Bulut LLM — faqat backend proxy orqali. Uchinchi tomon AI'ga ma'lumot yuborish uchun 5.1.2(i) bo'yicha oshkor qilish va ruxsat shart.
Manbalar {#manbalar}
- Apple Newsroom — Xcode 26.3 agentic coding
- Apple — Setting up coding intelligence
- Apple — Foundation Models framework
- WWDC25 — Meet the Foundation Models framework
- Apple TN3193 — Managing the on-device model's context window
- WWDC26 — Bring an LLM provider to Foundation Models (339)
- Apple Developer News — App Review Guidelines 5.1.2(i)
- OpenAI — Agentic AI Foundation (AGENTS.md)
- Claude Code — Data usage
- Anthropic TypeScript SDK