iOS
व्यू कंट्रोलर्स के बीच डाटा पास करना
खोज…
सेगमेंट का उपयोग करना (डेटा को आगे भेजना)
सेगमेंट का उपयोग करके वर्तमान दृश्य नियंत्रक से डेटा को अगले नए व्यू कंट्रोलर (पिछले व्यू कंट्रोलर नहीं) से पारित करने के लिए, पहले संबंधित स्टोरीबोर्ड में एक पहचानकर्ता के साथ एक सेगमेंट बनाएं। अपने वर्तमान दृश्य नियंत्रक की prepareForSegue
विधि को ओवरराइड करें। विधि के अंदर आप अपने पहचानकर्ता द्वारा बनाई गई बहस के लिए जाँच करें। डेस्टिनेशन व्यू कंट्रोलर पर कास्ट करें और डाउनकास्ट व्यू कंट्रोलर पर प्रॉपर्टीज़ सेट करके उसे डेटा पास करें।
एक सेगमेंट के लिए एक पहचानकर्ता सेट करना:
तर्क को प्रोग्रामबोर्ड पर सेट किया जा सकता है या स्टोरीबोर्ड में सेट किए गए बटन एक्शन इवेंट का उपयोग करके ctrl + को डेस्टिनेशन व्यू कंट्रोलर द्वारा ड्रैग किया जा सकता है। जब आप व्यू कंट्रोलर में सेग आइडेंटिफ़ायर का उपयोग करके प्रोग्राम से प्रोग्राम के लिए कॉल कर सकते हैं, तो:
उद्देश्य सी
- (void)showDetail {
[self performSegueWithIdentifier:@"showDetailingSegue" sender:self];
}
तीव्र
func showDetail() {
self.performSegue(withIdentifier: "showDetailingSegue", sender: self)
}
आप prepareForSegue
पेलोड को prepareForSegue
विधि के prepareForSegue
संस्करण में कॉन्फ़िगर कर सकते हैं। गंतव्य दृश्य नियंत्रक लोड होने से पहले आप आवश्यक गुण सेट कर सकते हैं।
उद्देश्य सी
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:@"showDetailingSegue"]){
DetailViewController *controller = (DetailViewController *)segue.destinationViewController;
controller.isDetailingEnabled = YES;
}
}
तीव्र
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetailingSegue" {
let controller = segue.destinationViewController as! DetailViewController
controller.isDetailingEnabled = true
}
}
DetailViewController
दूसरे दृश्य नियंत्रक का नाम है और isDetailingEnabled
उस दृश्य नियंत्रक में एक सार्वजनिक चर है।
इस पैटर्न पर विस्तार करने के लिए, आप किसी भी आवश्यक चर को शुरू करने में मदद करने के लिए, छद्म इनिशियलाइज़र के रूप में DetailViewController
पर एक सार्वजनिक विधि का इलाज कर सकते हैं। यह सेल्फ डॉक्यूमेंट वैरिएबल होगा जिसे इसके सोर्स कोड के माध्यम से पढ़े बिना DetailViewController
पर सेट करना होगा। यह भी एक आसान जगह है चूक डाल करने के लिए।
उद्देश्य सी
- (void)initVC:(BOOL *)isDetailingEnabled {
self.isDetailingEnabled = isDetailingEnabled
}
तीव्र
func initVC(isDetailingEnabled: Bool) {
self.isDetailingEnabled = isDetailingEnabled
}
डेलिगेट पैटर्न (डेटा वापस पास करना) का उपयोग करना
वर्तमान दृश्य नियंत्रक से डेटा को पिछले दृश्य नियंत्रक पर वापस भेजने के लिए, आप प्रतिनिधि पैटर्न का उपयोग कर सकते हैं।
यह उदाहरण मानता है कि आपने इंटरफ़ेस बिल्डर में एक सेगमेंट बनाया है और आपने showSecondViewController
लिए showSecondViewController
पहचानकर्ता सेट किया है। आउटलेट और कार्यों को निम्नलिखित कोड में नामों तक जाना चाहिए।
पहले देखें नियंत्रक
प्रथम दृश्य नियंत्रक के लिए कोड है
तीव्र
class FirstViewController: UIViewController, DataEnteredDelegate {
@IBOutlet weak var label: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondViewController", let secondViewController = segue.destinationViewController as? SecondViewController {
secondViewController.delegate = self
}
}
// required method of our custom DataEnteredDelegate protocol
func userDidEnterInformation(info: String) {
label.text = info
navigationController?.popViewControllerAnimated(true)
}
}
उद्देश्य सी
@interface FirstViewController : UIViewController <DataEnteredDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
SecondViewController *secondViewController = segue.destinationViewController;
secondViewController.delegate = self;
}
-(void)userDidEnterInformation:(NSString *)info {
_label.text = info
[self.navigationController popViewControllerAnimated:YES];
}
@end
हमारे कस्टम DataEnteredDelegate
प्रोटोकॉल के उपयोग पर ध्यान दें।
दूसरा दृश्य नियंत्रक और प्रोटोकॉल
दूसरे दृश्य नियंत्रक के लिए कोड है
तीव्र
// protocol used for sending data back
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: String)
}
class SecondViewController: UIViewController {
// making this a weak variable so that it won't create a strong reference cycle
weak var delegate: DataEnteredDelegate?
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: AnyObject) {
// call this method on whichever class implements our delegate protocol (the first view controller)
delegate?.userDidEnterInformation(textField.text ?? "")
}
}
उद्देश्य सी
@protocol DataEnteredDelegate <NSObject>
-(void)userDidEnterInformation:(NSString *)info;
@end
@interface SecondViewController : UIViewController
@property (nonatomic) id <DataEnteredDelegate> delegate;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction) sendTextBackButton:(id)sender{
[_delegate userDidEnterInformation:textField.text];
}
@end
ध्यान दें कि protocol
व्यू कंट्रोलर क्लास के बाहर है।
डेटा का उपयोग करते हुए पीछे की तरफ सेगेट में प्रवेश करें
इसके विपरीत, जो आपको वर्तमान व्यू कंट्रोलर से डेस्टिनेशन व्यू कंट्रोलर तक डेटा "फॉरवर्ड" पास करने देता है:
(VC1) -> (VC2)
"खोलना" का उपयोग करके आप इसके विपरीत कर सकते हैं, गंतव्य से डेटा पास करें या वर्तमान दृश्य नियंत्रक से इसके वर्तमान दृश्य नियंत्रक से:
(VC1) <- (VC2)
नोट : ध्यान दें कि उपयोग करने से आप पहले डेटा पास कर सकते हैं और बाद में वर्तमान व्यू कंट्रोलर (VC2) से निपट लेंगे।
यह कैसे करना है:
सबसे पहले, आपको वर्तमान दृश्य नियंत्रक (वीसी 1) में निम्नलिखित घोषणा को जोड़ना होगा जो कि वह दृश्य नियंत्रक है जिसे हम डेटा पास करना चाहते हैं:
@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)
महत्वपूर्ण बात यह है उपसर्ग का उपयोग करने के लिए है unwind
, इस "सूचित" Xcode है कि यह एक खोलना विधि आप अच्छी तरह से स्टोरीबोर्ड में इसका इस्तेमाल करने का विकल्प दे रहा है।
बाद में आपको विधि को लागू करने की आवश्यकता होगी, यह लगभग वास्तविक सेगमेंट के समान दिखता है:
@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)
{
if segue.identifier == "YourCustomIdentifer"
{
if let VC2 = segue.sourceViewController as? VC2
{
// Your custom code in here to access VC2 class member
}
अब आपके पास 2 विकल्प हैं कि आप कॉल को सुधारे:
- आप "हार्ड कोड" कर सकते हैं:
self.performSegueWithIdentifier("YourCustomIdentifier", sender: self)
जो जब भी आप प्रदर्शन करेंगे तब आप के लिए आराम करेंगेperformSegueWithIdentifier
- आप
storyboard
का उपयोग करके अपने "एक्ज़िट" ऑब्जेक्ट परstoryboard
मेथड को लिंक कर सकते हैं: ctrl + बटन को ड्रैग करें जिसे आप बर्न विधि को "एग्जिट" ऑब्जेक्ट पर करना चाहते हैं:
रिलीज और आपके पास अपनी कस्टम विधि को चुनने का विकल्प होगा:
क्लोजर का उपयोग करके डेटा पास करना (डेटा वापस पास करना)
डेलिवेट पैटर्न का उपयोग करने के बजाय, जो कि UIViewController
वर्ग के विभिन्न भाग में कार्यान्वयन को विभाजित करता है, आप डेटा को वापस और आगे पास करने के लिए closures
का भी उपयोग कर सकते हैं। यह मानकर कि आप UIStoryboardSegue
का उपयोग कर रहे हैं, prepareForSegue
तरीके में आप आसानी से एक कदम में नए नियंत्रक सेटअप कर सकते हैं
final class DestinationViewController: UIViewController {
var onCompletion: ((success: Bool) -> ())?
@IBAction func someButtonTapped(sender: AnyObject?) {
onCompletion?(success: true)
}
}
final class MyViewController: UIViewController {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let destinationController = segue.destinationViewController as? DestinationViewController else { return }
destinationController.onCompletion = { success in
// this will be executed when `someButtonTapped(_:)` will be called
print(success)
}
}
}
यह उपयोग का एक उदाहरण है और स्विफ्ट पर उपयोग करना बेहतर है, उद्देश्य-सी ब्लॉक का सिंटैक्स कोड को अधिक पठनीय बनाने के लिए इतना आसान नहीं है
कॉलबैक क्लोजर (ब्लॉक) पासिंग डेटा का उपयोग करना
यह विषय आईओएस विकास में एक शास्त्रीय मुद्दा है, और इसका समाधान अन्य उदाहरणों में पहले से ही दिखाया गया है। इस उदाहरण में, मैं एक और दैनिक आम उपयोग दिखाऊंगा: इस पृष्ठ पर delegate pattern
उदाहरण को कॉलबैक closure
में closure
करके डेटा पास करना!
delegate pattern
विधि से बेहतर एक बात यह है कि दो अलग-अलग स्थानों में कोड सेट करने के बजाय कोड को विभाजित करें (इस पृष्ठ पर प्रतिनिधि उदाहरण देखें, prepareForSegue
, userDidEnterInformation
) बल्कि उन्हें एक साथ इकट्ठा करना (केवल prepareForSegue
, मैं इसे दिखाऊंगा)
दूसरा दृश्य नियंत्रक से प्रारंभ करें
हमें यह पता लगाना चाहिए कि कॉलबैक का उपयोग कैसे करना है, तो क्या हम इसे लिख सकते हैं, यही कारण है कि हम दूसरे व्यू कंट्रोलर से शुरू करते हैं, क्योंकि हम कॉलबैक का उपयोग करते हैं: जब हमें नया टेक्स्ट इनपुट मिलता है, तो हम कॉलबैक के पैरामीटर को माध्यम के रूप में उपयोग करते हुए , कॉलबैक कहते हैं। पहले ViewController पर डेटा पास करने के लिए, ध्यान दें कि मैंने कॉलबैक के पैरामीटर का उपयोग करते हुए कहा था, यह बहुत महत्वपूर्ण है, नौसिखिए (जैसा कि मैं था) हमेशा इसे अनदेखा करते हैं और पता नहीं है कि कॉलबैक क्लोजर को ठीक से लिखना कहां शुरू करना है
तो इस मामले में, हम जानते हैं कि हमारा कॉलबैक केवल एक पैरामीटर लेता है: पाठ और उसका प्रकार String
, आइए इसे घोषित करें और इसे संपत्ति बनाएं क्योंकि हमें अपने पहले दृश्य नियंत्रक से आबादी की आवश्यकता है
मैं सिर्फ सभी delegate
भाग की टिप्पणी करता हूं और तुलना करने के लिए रखता हूं
class SecondViewController: UIViewController {
//weak var delegate: DataEnteredDelegate? = nil
var callback: ((String?)->())?
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: AnyObject) {
//delegate?.userDidEnterInformation(textField.text!)
callback?(input.text)
self.navigationController?.popViewControllerAnimated(true)
}
}
पहला दृश्य नियंत्रक समाप्त करें
आपको बस कॉलबैक क्लोजर पास करना है, और हम कर रहे हैं, क्लोजर हमारे लिए भविष्य का काम करेगा क्योंकि हम पहले ही इसे दूसरे व्यू कंट्रोलर में सेट कर चुके हैं
यह देखें कि delegate pattern
कोड की तुलना में यह हमारे कोड को कैसे छोटा बनाता है
//no more DataEnteredDelegate
class FirstViewController: UIViewController {
@IBOutlet weak var label: UILabel!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destinationViewController as! SecondViewController
//secondViewController.delegate = self
secondViewController.callback = { text in self.label.text = text }
}
}
// required method of our custom DataEnteredDelegate protocol
//func userDidEnterInformation(info: String) {
// label.text = info
//}
}
और आखिरी में, शायद आप में से कोई व्यक्ति यह देख कर भ्रमित हो जाएगा कि हम केवल डेटा (इस मामले में बंद) को केवल एक तरीके से पास कर रहे हैं, पहले व्यू कंट्रोलर से दूसरे में, कोई सीधे दूसरे व्यू कंट्रोलर से वापस नहीं आ रहा है, हम कैसे कर सकते हैं इसे एक संचार उपकरण के रूप में मानते हैं? हो सकता है कि आप वास्तव में इसे चलाएं और इसे स्वयं साबित करें, सभी मैं कहूंगा कि यह पैरामीटर है , यह कॉलबैक क्लोजर का पैरामीटर है जो डेटा वापस पारित कर रहा है!
संपत्ति असाइन करके (डेटा को आगे भेजते हुए)
पुश करने या पेश करने से पहले आप अगले व्यू कंट्रोलर की संपत्ति बताकर सीधे डेटा पास कर सकते हैं।
class FirstViewController: UIViewController {
func openSecondViewController() {
// Here we initialize SecondViewController and set the id property to 492
let secondViewController = SecondViewController()
secondViewController.id = 492
// Once it was assign we now push or present the view controller
present(secondViewController, animated: true, completion: nil)
}
}
class SecondViewController: UIViewController {
var id: Int?
override func viewDidLoad() {
super.viewDidLoad()
// Here we unwrapped the id and will get the data from the previous view controller.
if let id = id {
print("Id was set: \(id)")
}
}
}