इंटरैक्टिव SwiftUI प्रीव्यू बनाने के लिए, हर प्रीव्यू को उसकी अपनी स्थानीय स्थिति दें, एडिटर में एक ऑब्ज़र्वेबल व्यू मॉडल पास करें, और बाइंडिंग के ज़रिए संपादन योग्य प्रॉपर्टीज़ उपलब्ध कराएं। इस चरण-दर-चरण मार्गदर्शिका में कृत्रिम उदाहरण टेक्स्ट का उपयोग करके macOS के लिए एक छोटा लेबल एडिटर बनाया गया है।
चुनें कि प्रीव्यू की स्थिति कहाँ होनी चाहिए
इस काम में एक डेस्कटॉप एडिटर का प्रीव्यू दिखाना है, जिसमें कोई व्यक्ति लेबल का शीर्षक और विवरण टेक्स्ट बदलता है, फिर यह टॉगल करता है कि विवरण दिखाई दे या नहीं। एडिटर को तुरंत प्रतिक्रिया देनी चाहिए, और हर प्रीव्यू स्पष्ट उदाहरण कॉन्फ़िगरेशन के साथ शुरू होना चाहिए।
इंटरैक्शन के लिए जितना छोटा इनपुट पर्याप्त हो, उतना ही इस्तेमाल करें। Apple की सलाह है कि व्यू को केवल वही डेटा पास करें जिसकी उसे ज़रूरत है, क्योंकि जटिल निर्भरताओं से प्रीव्यू बनाना कठिन हो जाता है। स्थिर लेबल में स्ट्रिंग दी जा सकती है; एडिटर को अपनी स्थिति से लिखने योग्य कनेक्शन चाहिए। अपने इंटरफ़ेस फ़ाइलों में प्रीव्यू जोड़ना।
| व्यू को क्या चाहिए | उपयुक्त इनपुट | उदाहरण स्थिति कहाँ रखी जाए |
|---|---|---|
| स्थिर टेक्स्ट दिखाना | अपरिवर्तनीय स्ट्रिंग | सीधे प्रीव्यू में |
| अपने पैरेंट के स्वामित्व वाला एक मान संपादित करना | @Binding प्रॉपर्टी |
प्रीव्यू होस्ट में स्थानीय @State |
| कई संबंधित ऑब्ज़र्वेबल प्रॉपर्टीज़ संपादित करना | @Bindable के ज़रिए उपलब्ध कराया गया ऑब्ज़र्वेबल मॉडल |
प्रीव्यू होस्ट के @State में रखा मॉडल इंस्टेंस |
| एनवायरनमेंट के ज़रिए दिया गया मॉडल पढ़ना | एनवायरनमेंट निर्भरता | प्रीव्यू रूट पर स्पष्ट इंजेक्शन |
इस उदाहरण में, व्यू मॉडल में दो स्ट्रिंग, एक दृश्यता सेटिंग और गणना किया गया डिस्प्ले शीर्षक है। हर प्रीव्यू का अपना अलग इंस्टेंस है। इससे शुरुआती स्थितियाँ प्रीव्यू घोषणा के पास स्पष्ट दिखाई देती हैं और उदाहरण किसी साझा म्यूटेबल सिंगलटन पर निर्भर नहीं रहता।
macOS SwiftUI टारगेट तैयार करें
यहाँ दिखाई गई इनलाइन @Previewable सिंटैक्स के लिए Xcode 16 या उसके बाद का संस्करण इस्तेमाल करें। Apple ने यह मैक्रो Xcode 16 में पेश किया था। इस उदाहरण का डिप्लॉयमेंट टारगेट macOS 14 या उसके बाद का रखें, जहाँ SwiftUI Observation को सपोर्ट करता है; Apple का मौजूदा Previewable() संदर्भ भी macOS 14 की उपलब्धता बताता है। Xcode 16 रिलीज़ नोट्स, अपने ऐप में मॉडल डेटा प्रबंधित करना, Previewable()।
मौजूदा macOS SwiftUI ऐप टारगेट में LabelEditor.swift नाम की Swift फ़ाइल जोड़ें। अगले दो कोड ब्लॉक मिलकर इसका पूरा प्रीव्यू उदाहरण बनाते हैं। ऐप का मौजूदा एंट्री पॉइंट रखें; यह फ़ाइल मॉडल, एडिटर और प्रीव्यू परिभाषित करती है।
कोड समर्थित टूलचेन में @State वाला रूप इस्तेमाल करता है। Apple का मौजूदा दस्तावेज़ इसके कार्यान्वयन में अंतर बताता है: Xcode 26 और उससे पहले State प्रॉपर्टी रैपर इस्तेमाल करते हैं, जबकि Xcode 27 और उसके बाद State() मैक्रो इस्तेमाल करते हैं। जनरेट किए गए कोड की जाँच करते या इनिशियलाइज़ेशन की लागत पर विचार करते समय यह अंतर ध्यान में रखें। State, State()।
ऑब्ज़र्वेबल मॉडल और संपादन योग्य व्यू बनाएं
मॉडल पर @Observable लगाएँ, ताकि SwiftUI इंटरफ़ेस द्वारा पढ़ी जाने वाली प्रॉपर्टीज़ को ट्रैक कर सके। टेक्स्ट फ़ील्ड और टॉगल के लिए आवश्यक प्रॉपर्टी बाइंडिंग बनाने हेतु एडिटर में @Bindable इस्तेमाल करें। Apple ऑब्ज़र्वेबल मॉडल संपादित करने के लिए इस संयोजन का दस्तावेज़ देता है। अपने ऐप में मॉडल डेटा प्रबंधित करना, Bindable।
import Foundation
import Observation
import SwiftUI
@MainActor
@Observable
final class LabelViewModel {
var title: String
var detail: String
var showsDetail: Bool
init(
title: String,
detail: String,
showsDetail: Bool = true
) {
self.title = title
self.detail = detail
self.showsDetail = showsDetail
}
var displayedTitle: String {
let trimmed = title.trimmingCharacters(
in: .whitespacesAndNewlines
)
return trimmed.isEmpty ? "Untitled label" : trimmed
}
}
@MainActor
struct LabelEditor: View {
@Bindable var model: LabelViewModel
var body: some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 6) {
Text("Title")
TextField("Label title", text: $model.title)
}
VStack(alignment: .leading, spacing: 6) {
Text("Detail")
TextField("Label detail", text: $model.detail)
}
Toggle("Show detail", isOn: $model.showsDetail)
Divider()
Text("Rendered label")
.font(.caption)
.foregroundStyle(.secondary)
VStack(alignment: .leading, spacing: 8) {
Text(model.displayedTitle)
.font(.title2)
.fixedSize(horizontal: false, vertical: true)
if model.showsDetail {
Text(model.detail)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(
.quaternary,
in: RoundedRectangle(cornerRadius: 10)
)
}
.textFieldStyle(.roundedBorder)
.padding(20)
}
}
मॉडल जानबूझकर अपने इनिशियलाइज़र में सभी उदाहरण मान स्वीकार करता है। इसका इनिशियलाइज़र केवल स्थानीय प्रॉपर्टीज़ को असाइन करता है। फ़ॉलबैक गणना रेंडर किए गए लेबल में दिखने वाली चीज़ बदलती है, लेकिन किसी व्यक्ति द्वारा दर्ज शीर्षक को ओवरराइट नहीं करती: केवल स्पेस वाला शीर्षक संपादन योग्य रहता है, जबकि रेंडर किया गया परिणाम Untitled label दिखाता है।
एडिटर को उसका मॉडल कॉलर से मिलता है। इसकी @Bindable घोषणा $model.title जैसी बाइंडिंग उपलब्ध कराती है; स्थिति का स्वामित्व प्रीव्यू होस्ट के पास रहेगा। अगर यह व्यू केवल मॉडल के मान दिखाता, तो ऑब्ज़र्वेशन के लिए साधारण मॉडल रेफ़रेंस पर्याप्त होता। यहाँ बाइंडेबल स्टोरेज उपयोगी है, क्योंकि कंट्रोल को लिखने योग्य प्रॉपर्टी बाइंडिंग चाहिए। Bindable।
हर प्रीव्यू को स्वतंत्र उदाहरण स्थिति दें
इसी फ़ाइल में नीचे दी गई घोषणाएँ जोड़ें। हर घोषणा अपने स्पष्ट कृत्रिम मानों वाला मॉडल बनाती है। चौड़ाइयाँ लेआउट की जाँच के उदाहरण हैं, सुझाए गए न्यूनतम विंडो आकार नहीं।
#Preview("Standard label") {
@Previewable @State var model = LabelViewModel(
title: "Sample tile",
detail: "Blue square, medium size"
)
LabelEditor(model: model)
.frame(width: 420)
.preferredColorScheme(.light)
}
#Preview("Long label in a narrow editor") {
@Previewable @State var model = LabelViewModel(
title: "Sample collection with a longer descriptive label",
detail: "Round tiles arranged in three columns"
)
LabelEditor(model: model)
.frame(width: 300)
.preferredColorScheme(.dark)
}
#Preview("Blank title and hidden detail") {
@Previewable @State var model = LabelViewModel(
title: " ",
detail: "An optional detail line",
showsDetail: false
)
LabelEditor(model: model)
.frame(width: 420)
}
@Previewable स्थानीय स्थिति की घोषणा को #Preview से बनाए गए एम्बेडेड SwiftUI व्यू का हिस्सा बनाता है। Apple के दस्तावेज़ के अनुसार, टैग की गई घोषणाएँ उस जनरेट किए गए व्यू की प्रॉपर्टीज़ बन जाती हैं। घोषणा को प्रीव्यू क्लोज़र के रूट पर रखें; प्रीव्यू बॉडी के बाहर @Previewable इस्तेमाल करना त्रुटि है। Previewable()।
अब स्वामित्व की कड़ी स्पष्ट है: जनरेट किया गया प्रीव्यू होस्ट मॉडल को @State में रखता है, LabelEditor को मॉडल रेफ़रेंस मिलता है, और @Bindable उसकी संपादन योग्य प्रॉपर्टीज़ उपलब्ध कराता है। SwiftUI Observation मॉडल को स्टेट में रखने और उस रेफ़रेंस को चाइल्ड व्यू को पास करने का समर्थन करता है। State।
इनिशियलाइज़र के मानों को शुरुआती फ़िक्स्चर मानें। इंटरैक्टिव प्रीव्यू चलते समय उनमें बदलाव किया जा सकता है। किसी खास लेआउट को फिर से देखते समय, उसकी शुरुआती दिखावट की तुलना करने से पहले नया प्रीव्यू इंस्टेंस खोलें।
छोटे परिदृश्य मैट्रिक्स से व्यवहार जाँचें
LabelEditor.swift खोलें, Show Canvas चुनें और कैनवस टैब में किसी नाम वाले प्रीव्यू को चुनें। अगर कैनवस रुका हुआ है, तो Restart चुनें। टेक्स्ट इनपुट और कंट्रोल लॉजिक जाँचने के लिए Live मोड चालू करें। इन कंट्रोल का वर्णन Apple की मौजूदा कैनवस गाइड में है। कैनवस में प्रीव्यू के साथ इंटरैक्ट करना।
स्थिति की समस्याओं और लेआउट की समस्याओं को अलग-अलग पहचानने के लिए ये जाँच करें। अपेक्षित परिणाम उदाहरण के कोड से निकलते हैं; ये रिपोर्ट किए गए परीक्षण परिणाम नहीं हैं।
| परिदृश्य | कार्रवाई | अपेक्षित परिणाम |
|---|---|---|
| सामान्य लेबल | शीर्षक को Amber circle से बदलें |
रेंडर किया गया शीर्षक तुरंत बदलता है |
| विवरण की दृश्यता | Show detail बंद करें, फिर चालू करें |
विवरण गायब होता है और उसका टेक्स्ट बरकरार रहते हुए फिर दिखाई देता है |
| खाली शीर्षक | शीर्षक के सभी अक्षर मिटाएँ | रेंडर किया गया शीर्षक Untitled label बन जाता है |
| केवल स्पेस वाला शीर्षक | केवल स्पेस दर्ज करें | फ़ील्ड में स्पेस बने रहते हैं; रेंडर किया गया शीर्षक फ़ॉलबैक दिखाता है |
| संकरा एडिटर | लंबे शीर्षक वाला प्रीव्यू देखें | रेंडर किया गया शीर्षक कार्ड के भीतर अगली पंक्ति में जाता है |
| अलग फ़िक्स्चर | एक प्रीव्यू संपादित करें, फिर किसी नए अलग प्रीव्यू को देखें | दूसरे प्रीव्यू में उसके घोषित मॉडल मान शुरू से दिखाई देते हैं |
अगर टेक्स्ट दर्ज हो रहा है, लेकिन रेंडर किया गया आउटपुट नहीं बदलता, तो फ़ील्ड बाइंडिंग और आउटपुट द्वारा पढ़ी जाने वाली प्रॉपर्टी के बीच कनेक्शन जाँचें। यहाँ दोनों रास्ते सीधे या displayedTitle के ज़रिए model.title तक पहुँचते हैं। अगर दृश्यता टॉगल करने पर विवरण मिट जाता है, तो खाली मान असाइन करने वाला कोड ढूँढें; यह उदाहरण केवल showsDetail बदलता है।
अनुसंधान परिवेश में Swift कंपाइलर या macOS प्रीव्यू रनटाइम उपलब्ध नहीं था, इसलिए इन उदाहरणों को कंपाइल करके या चलाकर नहीं, बल्कि दस्तावेज़ित API से मिलाकर जाँचा गया। एडिटर में बदलाव करने से पहले Xcode में टारगेट बिल्ड करें और इंटरैक्शन जाँच पूरी करें।
साझा सेटअप को संपादन योग्य फ़िक्स्चर से अलग रखें
इतने छोटे मॉडल के लिए, स्थानीय रूप से इंस्टेंस बनाना हर प्रीव्यू को समझने में आसान रखता है। अगर कई प्रीव्यू को बाद में महँगे, दोबारा इस्तेमाल होने वाले सेटअप की ज़रूरत हो, तो Apple PreviewModifier उपलब्ध कराता है: उसका साझा कॉन्टेक्स्ट कैश होकर उसमें भाग लेने वाले प्रीव्यू में फिर इस्तेमाल होता है। इस API के लिए macOS 15 या उसके बाद का संस्करण चाहिए। PreviewModifier।
दस्तावेज़ित साझा व्यवहार से एक व्यावहारिक डिज़ाइन विकल्प निकलता है: स्वतंत्र रूप से संपादन योग्य फ़िक्स्चर मॉडल स्थानीय रखें, और साझा कॉन्टेक्स्ट केवल उस सेटअप के लिए रखें जिसे आप जानबूझकर भाग लेने वाले प्रीव्यू में फिर इस्तेमाल करना चाहते हैं। साझा म्यूटेबल मॉडल में किए गए संपादन भी साझा होंगे, जिससे अलग-अलग परिदृश्यों की तुलना कठिन हो सकती है।
अगर मौजूदा व्यू मॉडल को उसके प्रकार के आधार पर एनवायरनमेंट से प्राप्त करता है, तो प्रीव्यू रूट पर आवश्यक इंस्टेंस इंजेक्ट करें। Apple के दस्तावेज़ के अनुसार, अनुरोधित प्रकार का गैर-वैकल्पिक मॉडल न मिलने पर अपवाद आता है। इसलिए प्रीव्यू को वे निर्भरताएँ देनी चाहिए जिन्हें उसका चुना हुआ रूट वास्तव में पढ़ता है। अपने ऐप में मॉडल डेटा प्रबंधित करना।
AppKit और TextKit की सीमाएँ बनाए रखें
ऊपर दिया गया एडिटर SwiftUI कंट्रोल का उपयोग करता है। अगर आपके मौजूदा macOS एडिटर में AppKit टेक्स्ट व्यू है, तो उस व्यू को SwiftUI पदानुक्रम में जोड़ने के लिए NSViewRepresentable इस्तेमाल करें। उसे makeNSView के ज़रिए बनाएँ और कॉन्फ़िगर करें, फिर आने वाली SwiftUI स्थिति को updateNSView के ज़रिए लागू करें। जब संपादनों को वापस SwiftUI तक भेजना हो, तो AppKit डेलीगेट बदलावों को कोऑर्डिनेटर के ज़रिए फ़ॉरवर्ड करें। दर्शाए गए व्यू का फ़्रेम और बाउंड्स SwiftUI को नियंत्रित करने दें। NSViewRepresentable।
Apple AppKit व्यू और व्यू कंट्रोलर का सीधे प्रीव्यू भी समर्थित करता है। हालाँकि, @Previewable केवल SwiftUI के लिए है और सीधे AppKit प्रीव्यू पर लागू नहीं होता। AppKit कंटेंट के साथ इस लेख का स्थानीय-स्थिति पैटर्न अपनाने के लिए, उस representable को शामिल करने वाले SwiftUI होस्ट का प्रीव्यू करें। अपने इंटरफ़ेस फ़ाइलों में प्रीव्यू जोड़ना।
NSTextView बनाते समय अपना टेक्स्ट इंजन चुनना जारी रखें। Apple इनिशियलाइज़ेशन के समय TextKit 2 चुनने के लिए NSTextView(usingTextLayoutManager: true) दस्तावेज़ित करता है। उसका TextKit मार्गदर्शन यह भी बताता है कि TextKit 1 के layoutManager तक पहुँचने से उस टेक्स्ट-व्यू इंस्टेंस के लिए एकतरफ़ा फ़ॉलबैक शुरू हो सकता है। अगर आपका इच्छित इंजन TextKit 2 है, तो उसके उपयुक्त API इस्तेमाल करें; प्रीव्यू इन सीमाओं को नहीं हटाता। TextKit और टेक्स्ट व्यू में नया क्या है।
स्वामित्व की सीमा पर प्रीव्यू विफलताओं का पता लगाएँ
सबसे पहले बिल्ड डायग्नोस्टिक देखें। Swift मैक्रो कंपाइल समय पर कोड जनरेट करते हैं, इसलिए मैक्रो कॉल पर दिखने वाली त्रुटि जनरेट की गई घोषणाओं से संबंधित हो सकती है। कोड देखने के लिए Xcode का Editor > Expand Macro कमांड इस्तेमाल करें। मैक्रो लागू करना।
फिर स्टेट मैकेनिज़्म जाँचें। मौजूदा Combine-आधारित ObservableObject के लिए उससे मेल खाता स्वामित्व पैटर्न चाहिए: Apple चेतावनी देता है कि ऐसे ऑब्जेक्ट को State में रखने से उसकी प्रकाशित प्रॉपर्टीज़ के बदलाव ट्रैक नहीं होते और स्वामियों को StateObject इस्तेमाल करने का निर्देश देता है। यहाँ उदाहरण @Observable इस्तेमाल करता है, इसलिए इसकी स्थिति का स्वामित्व Observation पथ का अनुसरण करता है। State।
तैयार प्रीव्यू फ़ाइल में स्पष्ट शुरुआती मानों और दिखाई देने वाले इंटरैक्शन पर ध्यान रखें। सामान्य, लंबे शीर्षक और खाली शीर्षक वाले परिदृश्य अपेक्षा के अनुसार चलने लगें, तो इसी एडिटर को अपने ऐप के उपयुक्त पैरेंट व्यू के स्वामित्व वाले मॉडल के साथ इस्तेमाल करें। प्रीव्यू फ़िक्स्चर उन इंटरफ़ेस स्थितियों को दोबारा बनाने का छोटा और आसान तरीका बने रहते हैं।
स्रोत
- अपने इंटरफ़ेस फ़ाइलों में प्रीव्यू जोड़ना — Apple
- Xcode 16 रिलीज़ नोट्स — Apple
- अपने ऐप में मॉडल डेटा प्रबंधित करना — Apple
- Previewable() — Apple
- Bindable — Apple
- State — Apple
- State() — Apple
- कैनवस में प्रीव्यू के साथ इंटरैक्ट करना — Apple
- PreviewModifier — Apple
- NSViewRepresentable — Apple
- TextKit और टेक्स्ट व्यू में नया क्या है — Apple
- मैक्रो लागू करना — Apple