स्वचालित फॉर्म जनरेशन वाला मोबाइल एप्लिकेशन: हमारा मामला

मोबाइल एप्लिकेशन हमेशा सरल और संक्षिप्त नहीं होते हैं, जैसा कि हम डेवलपर्स को पसंद करते हैं। अन्य एप्लिकेशन जटिल उपयोगकर्ता समस्याओं को हल करने के लिए बनाए गए हैं और इनमें कई स्क्रीन और स्क्रिप्ट हैं। उदाहरण के लिए, परीक्षण, प्रश्नावली और सर्वेक्षण करने के लिए आवेदन - जहां भी आपको प्रक्रिया में कई फॉर्म भरने की आवश्यकता होती है। इस आवेदन पर इस लेख में चर्चा की जाएगी।



हमने उन एजेंटों के लिए एक मोबाइल एप्लिकेशन विकसित करना शुरू किया जो बीमा पॉलिसियों के ऑन-साइट पंजीकरण में लगे हैं। वे ग्राहक डेटा के साथ एप्लिकेशन में बड़े फॉर्म भरते हैं: कार, मालिकों, ड्राइवरों आदि के बारे में जानकारी। यद्यपि प्रत्येक फॉर्म के अपने खंड, कोशिकाएं और संरचना होती हैं, और प्रत्येक प्रश्नावली आइटम के लिए एक अद्वितीय डेटा प्रकार (स्ट्रिंग, तिथि, संलग्न दस्तावेज़) की आवश्यकता होती है, स्क्रीन फॉर्म काफी समान थे। लेकिन मुख्य बात उनकी संख्या है ... कोई भी एक ही तत्वों के दृश्य और प्रसंस्करण की पुनरावृत्ति में कई बार संलग्न नहीं होना चाहता है।

प्रपत्र बनाने पर कई घंटों के मैनुअल काम से बचने के लिए, आपको थोड़ा त्वरित बुद्धि और बहुत सारे गतिशील यूआई निर्माण को लागू करने की आवश्यकता है। इस लेख में, हम साझा करना चाहते हैं कि हमने इस समस्या को कैसे हल किया।

समस्या के एक सुरुचिपूर्ण समाधान के लिए, हमने वस्तुओं को उत्पन्न करने के लिए तंत्र का उपयोग किया - ViewModels, जो तालिकाओं का उपयोग करके कस्टम रूपों का निर्माण करने के लिए उपयोग किया जाता है।



सामान्य कार्य में, प्रत्येक व्यक्तिगत तालिका के लिए जिसे डेवलपर स्क्रीन पर देखना चाहता है, एक अलग ViewModel वर्ग बनाना होगा। यह तालिका के दृश्य घटक को परिभाषित करता है। हमने Enum क्षेत्रों के माध्यम से संरचना का एक सरल विवरण का उपयोग करते हुए, एक स्तर अधिक जाने और ViewModels और खुद को गतिशील रूप से तैयार करने का फैसला किया।

यह कैसे काम करता है


यह सब enum के साथ शुरू हुआ। प्रत्येक प्रोफ़ाइल के लिए हम एक अद्वितीय एनम बनाते हैं - ये हमारे प्रोफ़ाइल के अनुभाग हैं। इसकी एक विधि इस खंड में कोशिकाओं के सरणी को वापस करना है।

तालिका में कोशिकाएं अतिरिक्त कार्यों के साथ भी संलग्न होंगी जो कोशिकाओं के गुणों का वर्णन करेंगी। ऐसे कार्यों में, हम सेल का नाम, प्रारंभिक मूल्य निर्धारित करते हैं। बाद में जैसे पैरामीटर जोड़े गए

  • प्रदर्शन की जांच: कुछ कोशिकाओं को छिपाया जाना चाहिए,
  • "माता-पिता" कोशिकाओं की सूची: वे कोशिकाएं जिन पर इस सेल का मूल्य, सत्यापन या प्रदर्शन निर्भर करता है,
  • सेल प्रकार: मानों के साथ सरल कोशिकाएं, स्विच में कोशिकाएं, तत्वों को जोड़ने के कार्य के साथ कोशिकाएं आदि।

हम एक सामान्य अनुभाग के लिए बाध्य करने के लिए सामान्य प्रश्नावलीसंचालन अनुभाग प्रोटोकॉल के सभी खंडों की सदस्यता लेते हैं, हम तालिका के सभी कक्षों (QuestionnaireCellType) के साथ ऐसा ही करेंगे।

protocol QuestionnaireSectionCellType { var title: String { get } var sectionCellTypes: [QuestionnaireCellType] { get } } protocol QuestionnaireCellType { var title: String { get } var initialValue: Any? { get } var isHidden: Bool { get } var parentFields: [QuestionnaireCellType] { get } … } 

ऐसे मॉडल को भरना बहुत आसान होगा। हम बस सभी अनुभागों के माध्यम से चलते हैं, प्रत्येक अनुभाग में हम कक्षों की एक सरणी के माध्यम से चलाते हैं और उन्हें मॉडल सरणी में जोड़ते हैं।

पॉलिसीधारक की स्क्रीन के उदाहरण पर (वर्गों के साथ गणना - InsurantSectionType):

 final class InsurantModel: BaseModel<QuestionnaireCellType> { override init() { super.init() initParameters() } private func initParameters() { InsurantSectionType.allCases.forEach { type in type.sectionCellTypes.forEach { if let valueModel = ValueModel(type: $0, parentFields: $0.parentFields, value: $0.initialValue) { valueModels.append(valueModel) } } } } } 

हो गया! अब हमारे पास प्रारंभिक मूल्यों के साथ एक तालिका है। QuestionnaireCellType कुंजी के साथ मान को पढ़ने और इच्छित सरणी तत्व में सहेजने के लिए विधियाँ जोड़ें।

कुछ मॉडलों में वैकल्पिक क्षेत्र हो सकते हैं, इसलिए हमने वैकल्पिक कुंजियों के साथ एक सरणी जोड़ी। मॉडल सत्यापन के दौरान, इन कुंजियों में मान नहीं हो सकते हैं, लेकिन मॉडल को भरा हुआ माना जाएगा।

इसके अलावा, सुविधा के लिए, ValueModel के सभी मूल्य हम सामान्य प्रोटोकॉल की सदस्यता लेते हैं। संभावित मानों की सूची को सीमित करने के लिए StringRepresentable प्रोटोकॉल और सेल में मान प्रदर्शित करने के लिए एक विधि जोड़ते हैं।

 protocol StringRepresentable { var stringValue: String? { get } } 

कार्यक्षमता में वृद्धि हुई, और कई अन्य गुण और तरीके मॉडल में दिखाई दिए: मॉडल की सफाई (कुछ मॉडल में प्रारंभिक मान सेट किए जाने चाहिए), मूल्यों के एक गतिशील सरणी के लिए समर्थन (मूल्य: सरणी), आदि।

यह दृष्टिकोण दायरे का उपयोग कर डेटाबेस में भंडारण के लिए बहुत सुविधाजनक निकला। प्रश्नावली को भरने के लिए, पहले से सहेजे गए पूर्ण मॉडल का चयन करना संभव है। CTP नीति का विस्तार करने के लिए, एजेंट को अब उपयोगकर्ता के दस्तावेजों, उसके द्वारा संलग्न ड्राइवरों और नए के लिए टीसीपी डेटा को भरने की आवश्यकता नहीं होगी। इसके बजाय, आप इसे मौजूदा में भरने के लिए पुन: उपयोग कर सकते हैं।

तालिकाओं को बदलने या पूरक करने के लिए, आपको बस किसी विशेष स्क्रीन से संबंधित ViewModel को खोजने की आवश्यकता है, आवश्यक एनम को ढूंढें जो वांछित ब्लॉक को प्रदर्शित करने और कई मामलों को जोड़ने या ठीक करने के लिए जिम्मेदार है। सब कुछ, तालिका आवश्यक रूप लेगी!

परीक्षण मूल्यों के साथ फ़ॉर्म भरना भी बहुत सुविधाजनक और त्वरित था। इस तरह से आप किसी भी टेस्ट डेटा को जल्दी से जनरेट कर सकते हैं। और यदि आप प्रारंभिक डेटा के साथ एक अलग फ़ाइल जोड़ते हैं, जहां से प्रोग्राम प्रश्नावली के प्रत्येक विशिष्ट क्षेत्र में मान लेगा, तो एक शुरुआत भी तैयार किए गए प्रश्नावली को कोड के बाकी हिस्सों को छोड़कर और शेष कोड को अलग किए बिना उत्पन्न कर सकता है।

पर निर्भर करता है


एक अलग कार्य जिसे हमने विकास प्रक्रिया के दौरान हल किया है वह निर्भरता से निपटने का है। प्रश्नावली के कुछ तत्व आपस में जुड़े हुए थे। इसलिए, इस दस्तावेज़ के प्रकार को चुनने के बिना दस्तावेज़ संख्या नहीं भरी जा सकती है, शहर और सड़क आदि को इंगित किए बिना घर का नंबर इंगित नहीं किया जा सकता है।



हमने सभी निर्भर क्षेत्रों को साफ़ करने के साथ प्रश्नावली के मूल्यों को अद्यतन किया है (उदाहरण के लिए, दस्तावेज़ के प्रकार को हटाना या बदलना, हम फ़ील्ड "दस्तावेज़ संख्या" को साफ़ करते हैं):

 func updateValueModel(value: StringRepresentable?, for type: QuestionnaireCellType) { guard let model = valueModels.first(where: { $0.type.equal(to: type) }) else { return } model.value = value clearRelativeValues(type: type) } func clearRelativeValues(type: QuestionnaireCellType) { _ = valueModels.filter { $0.parentFields.contains(where: { $0.equal(to: type) }) } .compactMap { $0.type } .compactMap { updateValueModel(value: nil, for: $0) } } 

विकास के दौरान हल किए जाने वाले नुकसान, और हम कैसे कामयाब रहे


यह स्पष्ट है कि यह विधि एक ही कार्यक्षमता (फ़ील्ड्स में भरने) के साथ स्क्रीन के लिए सुविधाजनक है, लेकिन इतना सुविधाजनक नहीं है यदि एक अलग स्क्रीन पर अद्वितीय तत्व या फ़ंक्शन दिखाई देते हैं जो अन्य स्क्रीन पर नहीं हैं। हमारे आवेदन में, ये थे:

  • इंजन पावर वाली एक स्क्रीन, जिसे अलग से जेनरेट करना पड़ता था, यही वजह है कि यह कार्यक्षमता में भिन्न थी। इस स्क्रीन पर, अनुरोध दूर जाना चाहिए और सर्वर से मूल्य स्वचालित रूप से प्रतिस्थापित किया जाता है। मुझे इसके लिए अलग से एक वर्ग बनाना था जो सर्वर से लोड करने, सत्यापन करने, सत्यापन करने, लोड करने और खाली क्षेत्र में एक मूल्य को प्रतिस्थापित करने के लिए जिम्मेदार होगा, उपयोगकर्ता को परेशान किए बिना यदि बाद वाला अपना मूल्य दर्ज करने का निर्णय लेता है।
  • पंजीकरण संख्या स्क्रीन, जिसमें केवल एक ही स्विच है, जो पाठ क्षेत्र के प्रदर्शन या छुपाने को प्रभावित करता है। इस स्थिति के लिए, एक अतिरिक्त स्थिति बनानी होगी, जो प्रोग्राम को स्विच स्थिति के साथ रिक्त मान के रूप में मामलों का निर्धारण करेगा।
  • डायनेमिक सूची, जैसे कि ड्राइवरों की एक सूची जिसे संग्रहीत किया जाना था और एक फॉर्म से बंधा हुआ था, जो अवधारणा से बाहर निकल गया था।
  • अद्वितीय प्रकार के डेटा सत्यापन। यह regex'ami के साथ मिश्रित बहुत सारे मुखौटे हो सकते हैं। और विभिन्न क्षेत्रों के लिए तारीख सत्यापन, जहां सत्यापन नाटकीय रूप से भिन्न होता है (न्यूनतम / अधिकतम मूल्यों पर प्रतिबंध), आदि।
  • डेटा एंट्री स्क्रीन को कलेक्शन व्यू सेल के रूप में बनाया गया है। (यह डिजाइन द्वारा आवश्यक था!) ​​इस वजह से, मोडल खिड़कियों को प्रदर्शित करने से चयनित सूचकांक पर सटीक नियंत्रण की आवश्यकता होती है। मुझे भरने के लिए उपलब्ध फ़ील्ड की जांच करनी थी, और उस सूची से बाहर करना चाहिए जो उपयोगकर्ता को नहीं देखना चाहिए।
  • तालिका में डेटा को सही ढंग से प्रदर्शित करने के लिए, कुछ स्क्रीन के मॉडल के तरीकों में बदलाव करना आवश्यक था। कक्ष जैसे नाम और पता एक ही तत्व के रूप में प्रदर्शित किए जाते हैं, लेकिन पूरी तरह से भरने के लिए कई पॉप-अप स्क्रीन की आवश्यकता होती है।

निष्कर्ष


इस अनुभव ने ट्रू इंजीनियरिंग में हमें एक मोबाइल एप्लिकेशन को जल्दी से लागू करने की अनुमति दी, जिसे बनाए रखना आसान है। बहुमुखी प्रतिभा आपको जल्दी से विभिन्न प्रकार के इनपुट डेटा के साथ तालिकाओं को बनाने की अनुमति देती है: हमने केवल एक सप्ताह में 20 खिड़कियां बनाईं। यह दृष्टिकोण अनुप्रयोग परीक्षण प्रक्रिया को भी गति देता है। निकट भविष्य में, हम नए टेबल और नई कार्यक्षमता बनाने के लिए तैयार कारखाने का पुन: उपयोग करेंगे।

Source: https://habr.com/ru/post/hi459430/


All Articles