आपके द्वारा अनुमानित कार्यक्षमता वास्तव में मौजूद नहीं है। अलग-अलग रखें "ग्राफिक्स संदर्भ इस तरह से काम नहीं करते हैं (मुफ्त में)।" आपने UIGraphicsPushContext
और UIGraphicsPopContext
फ़ंक्शंस देखे होंगे, लेकिन वे जो भी आप यहां बात कर रहे हैं वह नहीं करते हैं। "पुश" और "पॉप" ऑपरेशंस वे ग्राफिक्स संदर्भ के गैर-प्रस्तुत किए गए पहलुओं पर काम करते हैं: वर्तमान भरने और स्ट्रोक रंग, क्लिप रेक्ट, और ट्रांसफॉर्म मैट्रिक्स उदाहरण के लिए। एक बार संदर्भ में कुछ प्रस्तुत किया जाता है - यानी एक पथ/rect/आदि। स्ट्रोक या भर दिया गया है, या एक छवि संदर्भ में मिश्रित किया गया है - यह हमेशा के लिए प्रस्तुत किया जाता है। "वापस जाने" का एकमात्र तरीका किसी भी तरह से पिछली स्थिति को फिर से बनाना है। दुर्भाग्यवश, UIGraphicsContext
पर कोई जादू निर्मित नहीं है जो आपके लिए ऐसा करेगा।
इस बारे में जाने के कई तरीके हैं। जैसा कि एक और उपयोगकर्ता ने उल्लेख किया है, आप प्रत्येक उपयोगकर्ता कार्रवाई के बाद संदर्भ की स्थिति को कैप्चर कर सकते हैं। संक्षेप में, इसका मतलब है कि आपका दस्तावेज़ "मॉडल" एक बिटमैप स्टैक है। यह बहुत जल्दी गहन गहन हो जाएगा - बिटमैप्स स्मृति-भारी हैं। निश्चित रूप से ऑप्टिमाइज़ेशन हैं जो आप इस दृष्टिकोण से अधिक लाभ प्राप्त करने के लिए कर सकते हैं, जैसे कि प्रत्येक फ्रेम के बीच बदल गए क्षेत्र को सहेजना, बिटमैप्स को संपीड़ित करना, डिस्क पर उन्हें स्वैप करना आदि। वास्तविक, उपयोग करने योग्य ऐप्स हैं ऐप स्टोर जो इस दृष्टिकोण का उपयोग कर काम करता है, लेकिन दृष्टिकोण स्वाभाविक रूप से सीमित है, और आप पूर्ववत राज्यों के अपने सहेजे गए ढेर को अनुकूलित और प्रबंधित करने में गैर-मामूली प्रयासों को समाप्त कर देंगे।
स्वाभाविक रूप से, विचार करने के लायक अन्य दृष्टिकोण हैं।सबसे सरल यह है कि आपका वास्तविक दस्तावेज़ मॉडल छोटे (यानी गैर-बिटमैप) डेटा संरचनाओं का ढेर होना चाहिए जो संदर्भ की स्थिति को फिर से बनाने के लिए आवश्यक संचालन का वर्णन करते हैं। जब उपयोगकर्ता अनदेखा करता है, तो आप बस स्टैक के शीर्ष पर ऑपरेशन को हटाते हैं और शेष स्टैक को वापस चलाकर ग्राफिक्स संदर्भ को फिर से बनाते हैं। यह "योजक" प्रकार के अनुप्रयोगों के लिए एक सभ्य दृष्टिकोण है (सोचें "ब्रश") लेकिन कैनवास पर एक आकार को स्थानांतरित करने के वर्णन के सरल परिदृश्य में भी गिरना शुरू होता है। यह अंततः बिटमैप स्टैक दृष्टिकोण के समान मुद्दों से ग्रस्त है - आपके पास जितना अधिक संचालन होता है, उतना ही लंबे समय तक राज्य को फिर से बनाने के लिए होता है, इसलिए आप अनिवार्य रूप से बिटमैप स्नैपशॉट्स को समय-समय पर समाप्त कर देते हैं।
ऑब्जेक्ट के लिए आपके द्वारा वर्णित कैनवास परिदृश्य ('आकृति आकार' ऑपरेशन), कई दृष्टिकोण भी हैं। एक क्लासिक दृष्टिकोण आपके दस्तावेज़ मॉडल को छोटे, अधिक विशिष्ट डेटा संरचनाओं का सेट होना होगा जो कैनवास की वर्तमान स्थिति का वर्णन करते हैं। Shape
कक्षा आदि के बारे में सोचें। सबसे सरल मामले में, जब कोई उपयोगकर्ता कैनवास में आयताकार जोड़ता है, तो Shape
उदाहरण आकार के जेड-ऑर्डर किए गए सरणी में जोड़ा जाता है। किसी भी समय आकृतियों की सूची में परिवर्तन होता है, संदर्भ जेड क्रम में प्रत्येक आकार को चित्रित करके पुन: उत्पन्न होता है। पूर्ववत कार्यक्षमता को प्राप्त करने के लिए, हर बार जब आप आकृतियों की सरणी को बदलते हैं, तो आप एक आमंत्रण रिकॉर्ड करने के लिए NSUndoManager
का भी उपयोग करते हैं, जब वापस खेले जाते हैं, तो विपरीत ऑपरेशन होने का कारण बनता है।
यदि आपका आकार-ऐड आपरेशन इस तरह देखा:
[shapeArray insertObject: newShape atIndex: 5];
तो फिर तुम, एक ही समय में, इस के साथ क्या करना होगा NSUndoManager
:
[[undoManager prepareInvocationWithTarget: shapeArray] removeObjectAtIndex: 5];
जब उपयोगकर्ता क्लिक पूर्ववत, NSUndoManager
उस आमंत्रण को वापस चलाता है, और shapeArray
को इसकी पूर्व स्थिति वापस कर दी जाती है। यह क्लासिक NSUndoManager
पैटर्न है। यह अच्छी तरह से काम करता है, लेकिन कुछ नुकसान भी हैं। उदाहरण के लिए, एप टर्मिनेशन में पूर्ववत स्टैक को जारी रखने के लिए यह जरूरी नहीं है। चूंकि ऐप टर्मिनेशन आईओएस पर आम हैं, और उपयोगकर्ता आमतौर पर एक ऐप को टर्मिनेशन में पूरी तरह से राज्य को पुनर्स्थापित करने की अपेक्षा करते हैं, एक दृष्टिकोण जिसमें आपका पूर्ववत स्टैक नहीं टिकेगा ऐप टर्मिनेशन आपकी आवश्यकताओं के आधार पर एक गैर-स्टार्टर हो सकता है। अन्य, अधिक जटिल दृष्टिकोण हैं, लेकिन वे इन विषयों में से एक पर अधिकतर भिन्नताएं हैं। Gang of Four book, Design Patterns से Command Pattern के बारे में पढ़ने के लिए एक क्लासिक लायक है।
कोई फर्क नहीं पड़ता कि आप किस दृष्टिकोण को चुनते हैं, इस तरह के आवेदन को विकसित करने के लिए एक चुनौती होगी। यह ग्राफ़िक पूर्ववत कार्यक्षमता केवल कुछ नहीं है जो "मुक्त" के लिए UIGraphicsContext
में बनाई गई है। आपने उदाहरण के लिए टिप्पणियों में कई बार पूछा है। मुझे यह कहने में खेद है, लेकिन यह एक जटिल पर्याप्त अवधारणा है कि किसी के लिए स्टैक ओवरफ्लो उत्तर की सीमाओं के भीतर एक कार्य उदाहरण प्रदान करने के लिए संभव नहीं है। उम्मीद है कि ये विचार और पॉइंटर्स सहायक हैं। निश्चित रूप से कुछ ओपन सोर्स ड्राइंग अनुप्रयोग भी हैं जिन्हें आप प्रेरणा के लिए देख सकते हैं (हालांकि मुझे आईओएस के लिए किसी भी ओपन सोर्स ड्राइंग एप्लिकेशन के बारे में व्यक्तिगत रूप से पता नहीं है।)
क्या आप सही उपयोग कर रहे हैं। यदि हां, तो आप बेंज़ीर पथ या सामान्य रेखा का उपयोग कर रहे हैं।थोड़ी अधिक जानकारी की आवश्यकता है –
मैं सही और सामान्य रेखाओं का उपयोग कर रहा हूं, कोई बेंज़ीर पथ नहीं। खींचने पर मैं आयताकार को एक नई स्थिति में ले जाता हूं और इसे फिर से चलाता हूं। अब जब मैं पूर्ववत बटन दबाता हूं तो मैं आयताकार की पिछली स्थिति में जाना चाहता हूं। –
मुझे लगता है कि इस फ़ंक्शन का उपयोग करके आप "UIGraphicsPopContext" – Exploring