মোডালভিউকন্ট্রোলারকে বরখাস্ত করুন এবং ডেটা ফেরত দিন


84

আমার কাছে দুটি ভিউ কন্ট্রোলার রয়েছে, প্রথম ভিউকন্ট্রোলার এবং দ্বিতীয় ভিউকন্ট্রোলার । আমি এই দ্বিতীয়টিটি আমার দ্বিতীয় ভিউকন্ট্রোলারে স্যুইচ করতে ব্যবহার করছি (আমি এটিতে একটি স্ট্রিংও দিয়ে যাচ্ছি):

secondViewController *second = [[secondViewController alloc] initWithNibName:nil bundle:nil];

second.myString = @"This text is passed from firstViewController!";

second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

[self presentModalViewController:second animated:YES];

[second release];

আমি প্রথমে ভিউ কনট্রোলারটিতে ফিরে যেতে এই কোডটি সেকেন্ডভিউ কনট্রোলার এ ব্যবহার করি:

[self dismissModalViewControllerAnimated:YES];

এই সব কাজ করে। আমার প্রশ্ন, আমি কীভাবে প্রথম ভিউকন্ট্রোলারের কাছে ডেটা পাস করব? আমি দ্বিতীয় ভিউকন্ট্রোলার থেকে ফার্স্টভিউ কনট্রোলারের মধ্যে একটি ভিন্ন স্ট্রিং পাস করতে চাই।

উত্তর:


142

আপনার প্রতিনিধি প্রোটোকল ব্যবহার করা দরকার ... এটি কীভাবে করবেন তা এখানে:

আপনার দ্বিতীয় ভিউকন্ট্রোলারের হেডার ফাইলে একটি প্রোটোকল ঘোষণা করুন। এটিকে ঐটির মত দেখতে হবে:

#import <UIKit/UIKit.h>

@protocol SecondDelegate <NSObject>
-(void)secondViewControllerDismissed:(NSString *)stringForFirst
@end


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;

আপনার বাস্তবায়নের (সেকেন্ডভিউকন্ট্রোল.আর) ফাইলটিতে মাইডিলেগেট সংশ্লেষ করতে ভুলবেন না:

@synthesize myDelegate;

আপনার ফার্স্টভিউকন্ট্রোলারের শিরোনাম ফাইলটিতে এটি করে সেকেন্ডডেলিগেট প্রোটোকলে সাবস্ক্রাইব করুন:

#import "SecondViewController.h"

@interface FirstViewController:UIViewController <SecondDelegate>

এখন আপনি যখন ফার্স্টভিউ কনট্রোলার-এ সেকেন্ডভিউ কনট্রোলার ইনস্ট্যান্ট করেন আপনার নিম্নলিখিতগুলি করা উচিত:

// If you're using a view controller built with Interface Builder.
SecondViewController *second = [[SecondViewController alloc] initWithNibName:"SecondViewController" bundle:[NSBundle mainBundle]];
// If you're using a view controller built programmatically.
SecondViewController *second = [SecondViewController new]; // Convenience initializer that uses alloc] init]
second.myString = @"This text is passed from firstViewController!";
second.myDelegate = self;
second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:second animated:YES];
[second release];

শেষ অবধি, আপনার প্রথম দর্শন নিয়ন্ত্রকের (ফার্স্টভিউ কনট্রোলারআরএম) জন্য বাস্তবায়নের ফাইলে সেকেন্ডভিউ নিয়ন্ত্রণকারীের জন্য সেকেন্ডডেলিগেটের পদ্ধতিটি বাস্তবায়ন করুন:

- (void)secondViewControllerDismissed:(NSString *)stringForFirst
{
    NSString *thisIsTheDesiredString = stringForFirst; //And there you have it.....
}

এখন আপনি যখন দ্বিতীয় দর্শন নিয়ামককে বরখাস্ত করতে চলেছেন আপনি প্রথম দর্শনের নিয়ামকটিতে প্রয়োগ করা পদ্ধতিটি চালু করতে চান। এই অংশটি সহজ। আপনি যা করেন তা হ'ল আপনার দ্বিতীয় দর্শন নিয়ামকটিতে বরখাস্ত কোডের আগে কিছু কোড যুক্ত করুন:

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!"];
}
[self dismissModalViewControllerAnimated:YES];

ডেলিগেট প্রোটোকলগুলি অত্যন্ত, অত্যন্ত, অত্যন্ত কার্যকর, তাদের সাথে নিজেকে পরিচয় করা আপনার পক্ষে ভাল হবে :)

এনএসএনটিফিকেশনগুলি এটি করার আরেকটি উপায়, তবে সেরা অনুশীলন হিসাবে, আমি যখন একাধিক ভিউকন্ট্রোলার বা অবজেক্টের মধ্যে যোগাযোগ করতে চাই তখন আমি এটি ব্যবহার করতে পছন্দ করি। আপনি এনএসএনটিফিকেশন ব্যবহার সম্পর্কে আগ্রহী হলে আমি আগে পোস্ট করা একটি উত্তর এখানে: অ্যাপিডেলিগেটের থ্রেড থেকে একাধিক ভিউ কন্ট্রোলারকে জুড়ে ফায়ারিং ইভেন্টগুলি

সম্পাদনা:

আপনি যদি একাধিক যুক্তি পাস করতে চান তবে বরখাস্তের আগে কোডটি এরকম দেখাচ্ছে:

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];

এর অর্থ হ'ল আপনার প্রথম ভিউকন্ট্রোলারের অভ্যন্তরে আপনার সেকেন্ডডেলিগেট পদ্ধতি বাস্তবায়ন এখন দেখতে দেখতে পাবেন:

- (void) secondViewControllerDismissed:(NSString*)stringForFirst argument2:(NSObject*)inObject1 argument3:(NSObject*)inObject2
{
    NSString thisIsTheDesiredString = stringForFirst;
    NSObject desiredObject1 = inObject1;
    //....and so on
}

আইওএসের জন্য অ্যাপলের ভিউ কন্ট্রোলার প্রোগ্রামিং গাইড অনুসারে দ্বিতীয় উপস্থাপনা নিয়ন্ত্রণকারীর মধ্যে দ্বিতীয় ভিউকন্ট্রোলারকে বরখাস্ত করা উচিত, উপস্থাপিত ব্যক্তিতে নয়।
মাইকেল 9

আপনি ইউআইটিএবলভিউর প্রতিনিধি সেট করেন নি এমন শব্দগুলি। আপনি যে কোডটি দিয়েছিলেন এবং কীভাবে আবার চেনাশোনা দিয়েছিলেন, আপনি কি এটি একটি প্রশ্ন হিসাবে পোস্ট করতে পারেন? আমি আপনাকে সাহায্য করতে সক্ষম হতে পারে।
সিড

4
@ মিশেল ডকুমেন্টেশনটিতে বলা হয়েছে যে স্বতঃকে বরখাস্ত করা কল কলকে উপস্থাপনার ভিউ কন্ট্রোলারের কাছে ফরোয়ার্ড করে। এছাড়াও, স্ব কল করা আপনার পক্ষে পরিষ্কার হওয়ার উপযোগী কারণ আপনি যে আইওএস সংস্করণটি লক্ষ্য করছেন (5 বা তার আগে) তার উপর নির্ভর করে উপস্থাপনাভিউ কনট্রোলার এবং প্যারেন্টভিউকন্ট্রোলারের মধ্যে স্যুইচ করার বিষয়ে আপনার চিন্তা করার দরকার নেই।
সিড

4
@ সত্য আমি সম্মত হই; ব্লক আশ্চর্যজনকভাবে দরকারী। আমি এই উত্তরটি কোনও মুহুর্তে সমর্থন ব্লকগুলিতে পরিবর্তন করার কথা ভাবছিলাম। তবে এই ক্ষেত্রে, আমি প্রতিনিধিটির উত্তরটি আপাতত দৃশ্যমান রেখেছি কারণ এটি আমাদের মডেলগুলিতে যেতে পারে এমন জিনিসগুলিতে হস্তক্ষেপ করার জন্য আরও কিছুটা স্বাধীনতা দেয়। আমি কেবল অলস এবং শীঘ্রই ব্লকগুলি ব্যবহার করতে এই উত্তরটি আপডেট করব :)
সিড

4
@ সিড ধন্যবাদ ভাই এটি আমার পক্ষে কাজ করে তবে আপনার কিছুটা পরিবর্তন করার দরকার। অনেক কিছুই পরিবর্তন হয়েছে। দয়া করে এটি সম্পাদনা করুন
চেনস্পাইল

40

আমি এখানে জায়গা থেকে দূরে যেতে পারে, কিন্তু আমি খুব ভার্বোস ডেলিগেট / প্রোটোকল পদ্ধতির চেয়ে ব্লক সিনট্যাক্সকে অনেক বেশি পছন্দ করতে শুরু করছি। আপনি যদি ভিসি 1 থেকে ভিসি 2 তৈরি করেন, ভিসি 2 তে একটি সম্পত্তি আছে যা আপনি ভিসি 1 থেকে সেট করতে পারেন যা একটি ব্লক!

@property (nonatomic, copy) void (^somethingHappenedInVC2)(NSString *response);

তারপরে, আপনি যখন ভিসি 2 তে কিছু ঘটে যা আপনি ভিসি 1 সম্পর্কে বলতে চান, আপনি কেবলমাত্র ভিসি 1 তে সংজ্ঞায়িত ব্লকটি কার্যকর করুন!

self.somethingHappenedInVC2(@"Hello!");

এটি আপনাকে ভিসি 2 থেকে ভিসি 1 এ আবার ডেটা পাঠাতে দেয়। ঠিক যাদু হিসাবে। আইএমও, প্রোটোকলের চেয়ে এটি অনেক সহজ / পরিষ্কার er ব্লকগুলি দুর্দান্ত এবং যতটা সম্ভব আলিঙ্গন করা দরকার।

সম্পাদনা - উন্নত উদাহরণ

ধরা যাক আমাদের একটি মেইনভিসি রয়েছে যা ব্যবহারকারীর কাছ থেকে কিছু ইনপুট পেতে আমরা অস্থায়ীভাবে শীর্ষে একটি মডালভিসি উপস্থাপন করতে চাই। মেইনভিসি থেকে এই মডেলভিসি উপস্থাপন করার জন্য, আমাদের এটিকে মেইনভিসির ভিতরে বরাদ্দ করা / আরম্ভ করতে হবে। খুব বেসিক স্টাফ। আচ্ছা আমরা যখন এই মোডালভিসি অবজেক্টটি করি তখন আমরা এটিতে একটি ব্লক সম্পত্তিও সেট করতে পারি যা আমাদের উভয় ভিসি অবজেক্টের মধ্যে সহজেই যোগাযোগ করতে দেয়। সুতরাং আসুন উপরে থেকে উদাহরণটি নেওয়া যাক এবং মডেলভিসির .h ফাইলে ফোলিংয়ের সম্পত্তিটি রাখুন:

 @property (nonatomic, copy) void (^somethingHappenedInModalVC)(NSString *response);  

তারপরে, আমাদের মেইনভিসিতে, আমরা একটি নতুন মডালভিসি অবজেক্ট বরাদ্দ করা / আরম্ভ করার পরে, আপনি মোডালভিসির ব্লক সম্পত্তিটিকে এভাবে সেট করুন:

ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}

সুতরাং আমরা কেবলমাত্র ব্লক সম্পত্তি সেট করে দিচ্ছি, এবং যখন ব্লকটি কার্যকর করা হয় তখন কী ঘটে তা সংজ্ঞায়িত করছি।

অবশেষে, আমাদের মোডালভিসিতে, আমাদের কাছে একটি টেবিলভিউ কনট্রোলার থাকতে পারে যা স্ট্রিংগুলির ডেটাসোর্স অ্যারে দ্বারা সমর্থনযুক্ত। একবার সারির নির্বাচন হয়ে গেলে, আমরা এরকম কিছু করতে পারি:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }

এবং অবশ্যই, প্রতিটি সময় আমরা মোডালভিসিতে একটি সারি নির্বাচন করি, আমরা মেইনভিসিতে ফিরে আমাদের এনএসলোগ লাইন থেকে একটি কনসোল আউটপুট পেতে যাচ্ছি। আশা করি এইটি কাজ করবে!


4
স্টোরিবোর্ডগুলি ব্যবহার করার পরে এটি কি এখনও কাজ করা উচিত? এখনই এটি আমার পক্ষে কাজ করছে না। শুধু একটি lldb ত্রুটি সঙ্গে প্রস্থান করুন। প্রধান ডিফ। আমি দেখতে পাচ্ছি ভিসির বরাদ্দ এখন একটি তাত্ক্ষণিক স্টোরিবোর্ড প্রবাহ। সম্পাদনা করুন এবং আমি ব্লকটি তৈরি করার আগে উপস্থাপন করছিলাম। স্থির।
malaki1974

4
আমি আপনার সাথে একমত :) আমি আমার উত্তর পোস্ট করেছি বেশ কিছুক্ষণ আগে। এখন, আমি ব্যবহারের উপর নির্ভর করে ব্লক / প্রোটোকল ব্যবহারের মধ্যে স্যুইচ করি। এই থ্রেডটি এখনও আজও বেশ সক্রিয় হিসাবে দেখা হচ্ছে, আমার কোনও কোনও সময়ে ব্লক অন্তর্ভুক্ত করার জন্য আমার উত্তরটি সম্পাদনা করা উচিত।
সিড

4
এটি সবচেয়ে স্বজ্ঞাত সমাধানটি এনেছে বলে এই উত্তরটি গ্রহণ করা দরকার।
সুকিথা উদুগামসুরিয়া

4
দুটি যথাযথ উত্তরের মধ্যে, এটি সেরা!
কিগকোলম্যান

4
এটি এখন পর্যন্ত আমার পছন্দের পদ্ধতি। দ্রুত মধ্যে এটি ক্লোজার দিয়ে সম্পন্ন হয়। প্রোটোকল বা এই "কুরুচিপূর্ণ" বিজ্ঞপ্তি ধ্রুবকগুলি নির্দিষ্ট করার প্রয়োজন নেই তবে ডেলিগেটস এবং বিজ্ঞপ্তিগুলি আরও অনেক ভাল। আপনি যদি উপস্থাপিত ভিসিতে ভেরিয়েবলের নামটি বন্ধ করে রাখেন তবে এটি খুব স্বজ্ঞাত কোড হতে পারে eg Vc.didCancel, vc.didFinish ... আপনি এটিকে প্রিফারফেসেগ এ উপস্থাপন করতে পারেন যা উপস্থাপন করে (আপনি যদি সেগগুলি ব্যবহার করছেন)।
হিক্সফিল্ড

4

হুম, বিজ্ঞপ্তি কেন্দ্রটি সন্ধান করুন এবং একটি বিজ্ঞপ্তিতে তথ্য ফেরত দিন। আপেল এখানে এটি গ্রহণ - আমি কারওর সাথে অন্য কোনও পরামর্শ না থাকলে আমি ব্যক্তিগতভাবে এই পদ্ধতিটি গ্রহণ করি


লিঙ্কটি আসলে এটি অতিরিক্ত জটিল করে তুলেছে, আপনার যা প্রয়োজন কেবল তা পর্যবেক্ষক (প্রথম দেখুন কন্ট্রোলার) এবং দ্বিতীয়টি থেকে নোটিফটি প্রেরণ করুন। আপনি নির্বাচিতদের একটি বিজ্ঞপ্তিতে নিয়োগ করতে পারেন এবং বিজ্ঞপ্তির মাধ্যমে ফেরত পাঠানো তথ্যও পেতে পারেন।
theiOSDude

2

দ্বিতীয় দেখার নিয়ামকটিতে একটি প্রতিনিধি প্রোটোকল সংজ্ঞায়িত করুন এবং প্রথমটিকে দ্বিতীয়টির প্রতিনিধি করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.