Scheme ใน Xcode คือการกำหนดค่าที่กำหนดวิธีการสร้าง ทดสอบ โปรไฟล์ และเก็บถาวรแอปสำหรับ iOS, macOS, watchOS หรือ tvOS แต่ละ Scheme ประกอบด้วยชุดการทำงาน (Build, Run, Test, Profile, Analyze, Archive) พร้อมพารามิเตอร์ อาร์กิวเมนต์ และตัวแปรสภาพแวดล้อมของตัวเอง ตาม Apple Developer Documentation, 2025 Scheme เป็นเครื่องมือหลักในการจัดการการกำหนดค่าการสร้างใน Xcode แทนที่การสลับพารามิเตอร์ด้วยตนเอง Xcode จะสร้าง scheme ให้แต่ละ target โดยอัตโนมัติเมื่อเปิดโปรเจกต์ครั้งแรก
ประเด็นสำคัญ
Scheme ใน Xcode คือไฟล์ XML (นามสกุล .xcscheme) ที่อธิบายลำดับการทำงานและพารามิเตอร์สำหรับการสร้างและวิเคราะห์แอป แต่ละ Scheme เชื่อมโยงกับ target หนึ่งหรือหลาย target และกำหนดว่าจะใช้การกำหนดค่าใด (Debug, Release, AdHoc) สำหรับแต่ละการทำงาน Scheme เทียบเท่ากับ Build Variant ใน Android แต่มีโครงสร้างที่ยืดหยุ่นกว่า: scheme เดียวสามารถมี target ต่างกันสำหรับการทำงานที่ต่างกันได้
Xcode จะสร้าง scheme ให้แต่ละ target โดยอัตโนมัติเมื่อเปิดโปรเจกต์ครั้งแรก ชื่อ scheme ตามค่าเริ่มต้นจะตรงกับชื่อ target หากโปรเจกต์มี target สำหรับทดสอบ Xcode จะเพิ่มลงในการทำงาน Test ของ scheme ของ target หลักโดยอัตโนมัติ สำหรับโปรเจกต์ที่มีหลาย target (แอปหลัก + watchOS + ส่วนขยาย) Xcode จะสร้าง scheme แยกสำหรับแต่ละ target แต่ก็สามารถสร้าง scheme เดียวที่สร้าง target ทั้งหมดพร้อมกันได้
Scheme จะถูกจัดเก็บในไดเรกทอรี xcshareddata/xcschemes/ (สำหรับแบบ shared) หรือ xcuserdata/<user>/xcschemes/ (สำหรับแบบ private) Scheme แบบ shared จะเข้าสู่ Git และใช้โดยทั้งทีม ส่วน scheme แบบ private จะถูกจัดเก็บในเครื่องและไม่ถูกซิงค์ ไฟล์ .xcscheme มีรูปแบบ XML โดยมีองค์ประกอบราก <Scheme> ภายในเป็นบล็อกสำหรับแต่ละการทำงาน: BuildAction, TestAction, LaunchAction, ProfileAction, AnalyzeAction, ArchiveAction
.xcscheme คือไฟล์ XML ที่สามารถแก้ไขด้วยตนเองหรือผ่าน Xcode องค์ประกอบหลัก: <BuildAction> (รายการ target ที่จะสร้าง), <TestAction> (ลิงก์ไปยัง target สำหรับทดสอบ), <LaunchAction> (การกำหนดค่าการเปิดใช้), <ProfileAction>, <AnalyzeAction>, <ArchiveAction> แต่ละบล็อกมีแอตทริบิวต์ buildConfiguration ซึ่งกำหนดว่าจะใช้การกำหนดค่าใด (Debug/Release) สำหรับการทำงานนั้น
Scheme ประกอบด้วยการทำงานหกอย่าง ซึ่งแต่ละอย่างสามารถตั้งค่าได้อย่างอิสระ การทำงาน Build กำหนดว่า target ใดจะถูกสร้างและตามลำดับใด การทำงาน Run กำหนดว่าแอปจะถูกเปิดอย่างไร: ด้วยอาร์กิวเมนต์ ตัวแปรสภาพแวดล้อม และการกำหนดค่าใด การทำงาน Test กำหนดว่าการทดสอบใดจะถูกเรียกใช้และตัวเลือกความครอบคลุมโค้ดใดเปิดใช้งาน การทำงาน Profile จะเปิดด้วยเครื่องมือ Instruments เพื่อการวิเคราะห์ประสิทธิภาพ การทำงาน Analyze จะวิเคราะห์โค้ดแบบสแตติกด้วย Clang Static Analyzer การทำงาน Archive จะสร้างเพื่อเผยแพร่บน App Store หรือแจกจ่ายแบบ AdHoc
สำหรับแต่ละการทำงานสามารถกำหนด build configuration แยกกันได้ โดยปกติจะใช้ Debug สำหรับ Run และ Test และใช้ Release สำหรับ Archive build configuration จะกำหนดชุดแฟล็กของคอมไพเลอร์ การปรับให้เหมาะสม และข้อมูลการดีบัก Xcode มีการกำหนดค่ามาตรฐานสองแบบ: Debug (ไม่มีการปรับให้เหมาะสม มีสัญลักษณ์การดีบัก) และ Release (มีการปรับให้เหมาะสม ไม่มีข้อมูลการดีบัก) นักพัฒนาสามารถเพิ่มการกำหนดค่าแบบกำหนดเองผ่าน project.xcconfig
การทำงาน Archive มีความสำคัญเป็นพิเศษ — ระบบจะสร้าง .xcarchive ซึ่งจะถูกส่งออกเป็น .ipa สำหรับ App Store หรือ AdHoc ในภายหลัง การทำงาน Archive ใช้การกำหนดค่า Release ตามค่าเริ่มต้น แต่สามารถสลับเป็น AdHoc หรือ Distribution ได้ ในการทำงาน Archive ยังมีแฟล็ก revealArchiveInOrganizer — หลังการเก็บถาวรเสร็จสิ้น Xcode จะเปิด Organizer เพื่อดำเนินการเพิ่มเติมกับไฟล์เก็บถาวร
<!-- ตัวอย่าง .xcscheme สำหรับแอป iOS -->
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ABCD1234"
BuildableName = "MyApp.app"
BlueprintName = "MyApp"
ReferencedContainer = "container:MyApp.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
enableAddressSanitizer = "YES">
</LaunchAction>
</Scheme>
การสร้าง scheme ใหม่ทำผ่านเมนู Xcode: Product → Scheme → New Scheme หรือปุ่ม "+" ในแผง Scheme (ถัดจากปุ่ม Run) เมื่อสร้างจะเลือก target ที่จะสร้าง scheme ให้ Xcode จะคัดลอกการตั้งค่าจาก scheme ที่มีอยู่โดยอัตโนมัติหากเลือกเป็น "duplicate" Scheme ใหม่จะถูกบันทึกเป็นแบบ private ตามค่าเริ่มต้น — เพื่อเผยแพร่ให้ทีมต้องเปิดใช้งาน Shared ใน Manage Schemes
หน้าต่าง Edit Scheme (Product → Scheme → Edit Scheme) มีหกแท็บตามจำนวนการทำงาน ในแต่ละแท็บสามารถเปลี่ยน build configuration อาร์กิวเมนต์การเปิดใช้ ตัวแปรสภาพแวดล้อม และแฟล็กสำหรับวินิจฉัย ในแท็บ Run มีตัวเลือก: executable (จะเปิดไบนารีใด), wait for executable to be launched (สำหรับดีบักกระบวนการที่เปิดขึ้น), debugger (LLDB หรือ None), launch arguments, environment variables และตัวเลือกเพิ่มเติม (Address Sanitizer, Thread Sanitizer, Main Thread Checker, Memory Management)
สำหรับการวินิจฉัย Address Sanitizer (ASan) จะตรวจจับการเข้าถึงนอกขอบเขต use-after-free และข้อผิดพลาดหน่วยความจำอื่นๆ ในโค้ด C/C++/ObjC Thread Sanitizer (TSan) จะตรวจจับการแข่งขันข้อมูล (data races) ในโค้ดแบบหลายเธรด Undefined Behavior Sanitizer (UBSan) จะตรวจจับพฤติกรรมที่ไม่ได้กำหนด เช่น การล้นของ int ที่มีเครื่องหมาย ตัวเลือกเหล่านี้มีอยู่ใน Edit Scheme → Run → Diagnostics และใช้งานได้เฉพาะกับบิลด์แบบ Debug การเปิดใช้งาน sanitizer ทั้งหมดอาจทำให้การเริ่มทำงานช้าลง 2-3 เท่า ดังนั้นจึงแนะนำให้เปิดใช้งานแบบเลือกสรร
แนวทางทั่วไปคือการสร้าง scheme แยกสำหรับแต่ละสภาพแวดล้อม: Dev, Staging, Production แต่ละ scheme ใช้ Build Configuration เดียวกัน (Debug สำหรับ Dev, Release สำหรับ Production) แต่มีอาร์กิวเมนต์การเปิดใช้ต่างกัน: -FIRAnalyticsDebugEnabled, -com.apple.CoreData.SQLDebug 1 สำหรับ Dev และไม่มีสำหรับ Production อาร์กิวเมนต์การเปิดใช้จะถูกส่งไปยัง UserDefaults (ProcessInfo.processInfo.arguments) และพร้อมให้อ่านเมื่อแอปเริ่มทำงาน ทำให้สามารถสลับ URL เซิร์ฟเวอร์ ระดับการบันทึก และฟีเจอร์ต่างๆ ได้โดยไม่ต้องแก้ไขโค้ด
Scheme แบบ shared ถูกจัดเก็บใน <project>.xcworkspace/xcshareddata/xcschemes/ หรือ <project>.xcodeproj/xcshareddata/xcschemes/ และเข้าสู่ที่เก็บ Git นักพัฒนาทุกคนในทีมเห็น scheme เหล่านี้ใน Xcode Scheme แบบ shared เป็นวิธีเดียวในการแจกจ่าย scheme ภายในทีม หากนักพัฒนาสร้าง scheme ที่สำคัญ (เช่น "Staging Archive") แต่ไม่ได้ทำเครื่องหมายเป็น Shared ทีมที่เหลือจะมองไม่เห็น ทำให้เกิดความสับสน: ทุกคนจะสร้าง scheme ของตัวเองพร้อมการตั้งค่าของตัวเอง
Scheme แบบ private ถูกจัดเก็บใน xcuserdata/<user>/xcschemes/ และไม่เข้าสู่ Git มีประโยชน์สำหรับการกำหนดค่าส่วนบุคคล เช่น scheme ที่เปิดใช้งาน sanitizer ทั้งหมดสำหรับนักพัฒนาเฉพาะราย Scheme แบบ private ไม่ควรมีการตั้งค่าที่สำคัญซึ่งการสร้างโปรเจกต์ขึ้นอยู่กับ — หากนักพัฒนาออกจากโปรเจกต์ scheme แบบ private ของเขาจะหายไป คำแนะนำ: scheme ทั้งหมดที่ใช้ใน CI/CD และใช้โดยนักพัฒนาอย่างน้อยสองคนควรเป็นแบบ Shared
การจัดการ scheme ทำผ่าน Manage Schemes (Product → Scheme → Manage Schemes) หน้าต่างแสดง scheme ทั้งหมดของโปรเจกต์ สถานะ (Shared/Private) และปุ่ม +/− สำหรับเพิ่ม/ลบ ช่องทำเครื่องหมาย Shared จะสลับการมองเห็น scheme สำหรับทีม ในกรณีที่ Git ขัดแย้ง (การเปลี่ยนแปลง .xcscheme โดยนักพัฒนาสองคน) ต้องแก้ไขการรวมอย่างระมัดระวัง — ไฟล์ XML อาจมีตัวระบุ target ที่ต่างกัน แนะนำให้เพิ่ม .xcscheme ในไฟล์ที่ถูกล็อกระหว่างการ merge (git lfs หรือ .gitattributes)
Arguments (อาร์กิวเมนต์) ใน Scheme คือสตริงที่ส่งให้แอปเมื่อเปิดใช้ (ProcessInfo.processInfo.arguments) และตัวแปรสภาพแวดล้อม (ProcessInfo.processInfo.environment) อาร์กิวเมนต์ใช้สำหรับแฟล็ก: -AppleLanguages (ru), -AppleLocale ru_RU เพื่อจำลองภาษาและภูมิภาคแบบรัสเซีย หรือ -FIRDebugEnabled เพื่อเปิดการดีบัก Firebase ตัวแปรสภาพแวดล้อมใช้สำหรับการกำหนดค่า: API_BASE_URL=http://localhost:3000, LOG_LEVEL=debug
สำหรับการจัดการฟีเจอร์ (feature flags) ในสภาพแวดล้อมที่แตกต่างกัน จะใช้การรวมกันของ Arguments + Build Configuration ใน scheme แบบ Dev ตั้งอาร์กิวเมนต์ -FeatureFlagNewOnboarding YES และใน Production — -FeatureFlagNewOnboarding NO (หรือไม่มีอาร์กิวเมนต์) ในโค้ดการตรวจสอบ: UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding") วิธีการนี้ช่วยให้เปิดฟีเจอร์ทีละน้อยบน staging โดยไม่ต้องแก้ไขโค้ดและไม่ต้องคอมมิตค่าของ production
สำคัญ: อาร์กิวเมนต์และตัวแปรสภาพแวดล้อมของ Scheme จะแทนที่ค่าจาก Info.plist หากระบุ API_URL ใน Info.plist และใน Scheme — API_URL=http://localhost สำหรับการทำงาน Run เมื่อเปิดจาก Xcode จะใช้ค่าจาก Scheme เมื่อเปิดบนอุปกรณ์ (ไม่ใช่จาก Xcode) — ค่าจาก Info.plist สะดวกสำหรับการพัฒนาท้องถิ่น แต่ต้องจำไว้ว่าตัวแปรของ Scheme ไม่เข้าไปในบิลด์ — ตัวแปรเหล่านี้ทำงานเฉพาะเมื่อเปิดผ่าน Xcode
import Foundation
struct AppEnvironment {
var apiBaseURL: String {
ProcessInfo.processInfo.environment["API_BASE_URL"]
?? Bundle.main.object(forInfoDictionaryKey: "API_BASE_URL") as? String
?? "https://api.production.com"
}
var isDebugMode: Bool {
ProcessInfo.processInfo.arguments.contains("-DebugModeEnabled")
}
var isNewOnboardingEnabled: Bool {
UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding")
}
}
// ใช้งานเมื่อเริ่มต้น
let env = AppEnvironment()
NetworkConfig.shared.configure(baseURL: env.apiBaseURL)
ใน CI/CD (GitHub Actions, Jenkins, GitLab CI) Scheme ถูกใช้เป็นอาร์กิวเมนต์หลักของคำสั่ง xcodebuild ตัวอย่าง: xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphoneos archive แฟล็ก -scheme ระบุว่าจะใช้ scheme ใด xcodebuild อ่านการตั้งค่าทั้งหมดจากไฟล์ .xcscheme รวมถึง build configuration target และลำดับการสร้าง ซึ่งรับประกันว่า CI/CD จะสร้างแอปด้วยพารามิเตอร์เดียวกับ IDE ในเครื่อง
สำหรับ CI/CD scheme แบบ shared มีความสำคัญ หาก scheme ไม่เป็นแบบ Shared xcodebuild จะหามันไม่พบในที่เก็บ และการสร้างจะล้มเหลวด้วยข้อผิดพลาด "Scheme not found" กฎ: ก่อนตั้งค่า CI/CD ตรวจสอบให้แน่ใจว่า scheme ทั้งหมดที่ใช้ถูกทำเครื่องหมายเป็น Shared กฎข้อที่สอง: ใน CI/CD อย่าใช้ scheme ตามค่าเริ่มต้น (Xcode จะเลือก scheme แรกโดยอัตโนมัติ) — ควรส่งชื่อ scheme อย่างชัดเจนผ่านแฟล็ก -scheme เสมอ
สำหรับการสร้างหลาย scheme แบบขนาน (เช่น แอปและส่วนขยาย watchOS) สามารถรัน xcodebuild แบบต่อเนื่องหรือขนานได้ ระบบ CI สมัยใหม่ช่วยให้สามารถสร้าง scheme ต่างกันแบบขนานผ่านเมทริกซ์: หนึ่งจ็อบสร้างแอป iOS ส่วนอีกจ็อบสร้างส่วนขยาย watchOS ซึ่งช่วยลดเวลาการสร้างทั้งหมดจาก 15 นาทีเป็น 8 นาทีด้วยเอเจนต์แบบขนานสองตัว ในตอนท้ายอาร์ติแฟกต์จะถูกรวมเป็น .xcarchive เดียวด้วย xcodebuild -exportArchive
#!/bin/bash — การสร้าง CI/CD ด้วย xcodebuild
# 1. ทำความสะอาดและสร้าง
xcodebuild clean archive \
-workspace "MyApp.xcworkspace" \
-scheme "MyApp Production" \
-configuration Release \
-sdk iphoneos \
-archivePath "build/MyApp.xcarchive" \
CODE_SIGN_STYLE="Manual" \
PROVISIONING_PROFILE_SPECIFIER="match AppStore"
# 2. ส่งออกเป็น IPA
xcodebuild -exportArchive \
-archivePath "build/MyApp.xcarchive" \
-exportPath "build/ipa" \
-exportOptionsPlist "ExportOptions.plist"
คำถามที่พบบ่อย
โดยปกติ 2-3 scheme ก็เพียงพอ: Development (Debug), Staging (พร้อมอาร์กิวเมนต์สำหรับเซิร์ฟเวอร์ทดสอบ) และ Production (Release) สำหรับไลบรารีแบบโมดูลาร์ — หนึ่ง scheme พร้อมการตั้งค่าการทดสอบ อย่าสร้าง scheme มากเกินไป — scheme ใหม่ทุกอันต้องมีการดูแลรักษา
Build Configuration (Debug/Release) คือชุดแฟล็กคอมไพเลอร์ที่กำหนดใน .xcconfig Scheme คือชุดการทำงาน โดยแต่ละการทำงานอ้างอิง Build Configuration scheme บอกว่า "เมื่อเปิดใช้ให้ใช้ Debug" ส่วนการกำหนดค่าเป็นตัวกำหนดว่า "Debug หมายถึงไม่มีการปรับให้เหมาะสม มีสัญลักษณ์"
อาร์กิวเมนต์จะเข้าไปใน ProcessInfo.processInfo.arguments และ UserDefaults (หากอาร์กิวเมนต์ขึ้นต้นด้วยเครื่องหมายขีด) ตัวแปรสภาพแวดล้อมจะเข้าไปใน ProcessInfo.processInfo.environment ในโค้ด: UserDefaults.standard.bool(forKey: "FeatureFlag") สำหรับอาร์กิวเมนต์รูปแบบ -FeatureFlag YES
ได้ ใน Build Action สามารถเพิ่มหลาย target ได้ ตัวอย่างเช่น scheme "App + Watch + Widget" จะสร้างทั้งสาม target แบบต่อเนื่อง (หาก parallelizeBuildables=NO) หรือแบบขนาน (YES) สำหรับการเก็บถาวรแอป แค่ target หลักก็เพียงพอ — ที่เหลือจะถูกสร้างเป็น dependency
Swift Package Manager ไม่ได้แทนที่ scheme — scheme ยังคงกำหนดว่าจะใช้ การกำหนดค่าใดในการสร้าง SPM dependencies ทดสอบใดที่ต้องรัน และวิธีเก็บถาวร แพ็กเกจ SPM สามารถมี scheme ของตัวเองได้ ซึ่งจะถูกนำเข้าไปยังโปรเจกต์โดยอัตโนมัติเมื่อเพิ่มแพ็กเกจ
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ