Görünüşü nəzarət edənlər arasında məlumat ötürülməsi

Mən iOS və Objective-C və bütün MVC paradiqmasına yeniyəm və aşağıdakılarla sıxılmışam:

Məlumat giriş forması kimi çıxış edən bir baxış var və istifadəçiyə birdən çox məhsul seçmək imkanı vermək istəyirəm. Məhsullar UITableViewController istifadə edərək fərqli bir görünüşdə verilmiş və bir neçə variant daxil etmişəm.

Mənim sualım: məlumatları bir baxımdan digərinə necə ötürə bilərəm? Seçimi UITableView də bir UITableView , ancaq bu formu təqdim edildikdə Core Data-dakı digər məlumatlarla birlikdə saxlanıla biləcəyinə dair məlumatın daxil formasının əvvəlki görünüşünə necə ötürə bilərəm?

Baxdım və bəzi adamlar ərizə nümayəndəsində bir sıra elan etdilər. Singletones haqqında bir şey oxudum amma nə olduğunu başa düşmürəm və məlumat modelini yaratmaq üçün bir şey oxudum.

Bunu etmək üçün doğru yol nə olacaq və bunu necə edəcəyəm?

1227
06 марта '11 в 15:43 2011-03-06 15:43 Matt Qiyməti martın 06-da saat 11: 00-da təyin olunub
@ 39 cavab
  • 1
  • 2

Bu sual, stackoverflow'ta burada çox məşhur görünür, buna görə də, mənim kimi iOS dünyada başlayan insanlara kömək etmək üçün ən yaxşı cavabı verməyə qərar verdim.

Ümid edirəm ki, bu cavab mənə heç bir şey qaçırmayıblar ki, anlamaq üçün kifayət qədər aydındır.

İrəli məlumatlar

Veriyi başqa bir nəzarətçidən görünüş nəzarətçisinə göndərin. Bir obyektin / dəyərin bir görünüş nəzarətçisindən naviqasiya yığınını tıklaya biləcəyiniz başqa bir görünüş nəzarətçisinə köçürmək istəyirsinizsə, bu metoddan istifadə etməlisiniz.

Bu nümunədə ViewControllerAViewControllerB

BOOL dəyərini ViewControllerA köçürmək üçün aşağıdakıları edəcəyik.

  1. ViewControllerB.h BOOL üçün əmlak yaratmaq

     @property (nonatomic, assign) BOOL isSomethingEnabled; 
  2. ViewControllerA yə bu barədə istifadə ViewControllerB

     #import "ViewControllerB.h" 

    Daha sonra, məsələn, təqdimatı harada yükləmək istəyirsiniz. didSelectRowAtIndex ya da naviqasiya yığınında ViewControllerB əvvəl ViewControllerB üçün əmlakı təyin etmək üçün lazım olan bəzi IBAction .

     ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil]; viewControllerB.isSomethingEnabled = YES; [self pushViewController:viewControllerB animated:YES]; 

    Bu, ViewControllerB ildə BOOL YES üçün isSomethingEnabled olacaq.

Segues ilə məlumatların irəli göndərilməsi

Hikayələr istifadə edirsinizsə, çox ehtimal segues istifadə edəcəyik və məlumatları irəli ötürmək üçün bu prosedura ehtiyacınız olacaq. Bu, yuxarıda göstərilənlərə bənzəyir, ancaq bir görünüş nəzarətçisi tıklamadan əvvəl məlumatların köçürülməsinə əvəzli olaraq istifadə edilən bir üsuldan istifadə edirsiniz

 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

Beləliklə, ViewControllerA dan ViewControllerA a BOOL ötürmək üçün aşağıdakıları edəcəyik:

  1. ViewControllerB.h BOOL üçün əmlak yaratmaq

     @property (nonatomic, assign) BOOL isSomethingEnabled; 
  2. ViewControllerA yə bu barədə istifadə ViewControllerB

     #import "ViewControllerB.h" 
  3. ViewControllerA dan ViewControllerA -də storyboard üzərinə yaradın və bir nümunə verin, bu nümunədə onu "showDetailSegue"

  4. Sonra bir seque icra edildikdə çağırılan ViewControllerA metodunu əlavə etmək lazımdır, ona görə biz hansı zəngin təyin olunduğunu və sonra bir şey edəcəyimizi müəyyənləşdirməliyik. "showDetailSegue" kontrol edəcəyik və bunu "showDetailSegue" , BOOL ViewControllerB verəcəyik

     -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if([segue.identifier isEqualToString:@"showDetailSegue"]){ ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController; controller.isSomethingEnabled = YES; } } 

    Naviqasiya nəzarətçisinə quraşdırılmış öz fikirləriniz varsa yuxarıdakı metodu bir az aşağıda dəyişmək lazımdır

     -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if([segue.identifier isEqualToString:@"showDetailSegue"]){ UINavigationController *navController = (UINavigationController *)segue.destinationViewController; ViewControllerB *controller = (ViewControllerB *)navController.topViewController; controller.isSomethingEnabled = YES; } } 

    Bu, ViewControllerB ildə BOOL YES üçün isSomethingEnabled olacaq.

Geri məlumat ötürülməsi

Data ViewControllerB məlumatların ötürülməsi üçün protokol və nümayəndələri və ya blokları istifadə ViewControllerA , sonuncu geri çağırışlar üçün zərif birləşdirilmiş mexanizm kimi istifadə edilə bilər.

Bunu etmək üçün, ViewControllerA nümayəndəsini ViewControllerA edəcəyik. Bu, ViewControllerB geri göndərmək üçün bizə imkan verən ViewControllerA a bir mesaj göndərməyə imkan verir.

ViewControllerA nümayəndəsi olması üçün, biz göstərməliyik ki ViewControllerB protokoluna uyğun olmalıdır. Bu, ViewControllerA a tətbiq etməsi lazım olan üsulları bildirir.

  1. ViewControllerB.h , #import aşağıda, lakin yuxarıda @interface üstündəki protokolu müəyyənləşdirirsiniz.

     @class ViewControllerB; @protocol ViewControllerBDelegate <NSObject> - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item; @end 
  2. ViewControllerB.h növbəti delegate xüsusiyyətini təyin etmək və onu ViewControllerB.m sintez etmək lazımdır.

     @property (nonatomic, weak) id <ViewControllerBDelegate> delegate; 
  3. ViewControllerB ildə görünüş nəzarətçisini ViewControllerB mesaj delegate çağırırıq.

     NSString *itemToPassBack = @"Pass this value back to ViewControllerA"; [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack]; 
  4. Bu ViewControllerB . İndi ViewControllerA.h ViewControllerA idxal et və onun protokolunu izah etsin.

     #import "ViewControllerB.h" @interface ViewControllerA : UIViewController <ViewControllerBDelegate> 
  5. ViewControllerA.m protokolumuzdan aşağıdakı üsul tətbiq ViewControllerA.m

     - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item { NSLog(@"This was returned from ViewControllerB %@",item); } 
  6. ViewControllerB naviqasiya yığınına viewControllerB əvvəl ViewControllerB demək lazımdır ki ViewControllerA onun nümayəndəsi, əks halda biz bir səhv alırıq.

     ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil]; viewControllerB.delegate = self [[self navigationController] pushViewController:viewControllerB animated:YES]; 

Tövsiyələr

  1. Görünüşü nəzarətçi proqramlaşdırma təlimatında digər görünüşü nəzarətçiləri ilə ünsiyyət qurmaq üçün nümayəndəliyi istifadə edin
  2. Nümayəndə heyəti şablonu

NSNotification Mərkəzi Bu, məlumatların ötürülməsinin başqa bir üsuludur.

 // add observer in controller(s) where you want to receive data [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil]; -(void) handleDeepLinking:(NSNotification *) notification { id someObject = notification.object // some custom object that was passed with notification fire. } // post notification id someObject; [NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject]; 

Məlumatları bir sinifdən digərinə ötürmək (sinif hər hansı bir nəzarətçi, şəbəkə / sessiya meneceri, UIView alt sinfi və ya hər hansı digər sinif ola bilər)

Bloklar anonim funksiyalardır.

Bu nümunədə məlumat B nəzarətçisindən A nəzarətçisinə ötürülür

bloku müəyyənləşdirin

 @property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h 

bir dəyərə ehtiyac duyduğunuz bir blok işleyicisi (dinləyici) əlavə edin (məsələn, ControllerA'da API cavabına ehtiyacınız var və ya ContorllerB-dən A-a ehtiyacınız var)

 // in ContollerA.m - (void)viewDidLoad { [super viewDidLoad]; __unsafe_unretained typeof(self) weakSelf = self; self.selectedVoucherBlock = ^(NSString *voucher) { weakSelf->someLabel.text = voucher; }; } 

B nəzarətçisinə gedin

 UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"]; vc.sourceVC = self; [self.navigationController pushViewController:vc animated:NO]; 

yanğın bloku

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { NSString *voucher = vouchersArray[indexPath.row]; if (sourceVC.selectVoucherBlock) { sourceVC.selectVoucherBlock(voucher); } [self.navigationController popToViewController:sourceVC animated:YES]; } 

Bloklar üçün başqa bir iş nümunəsi

1578
16 марта '12 в 14:39 2012-03-16 14:39 Cavab Matt Qiymət tərəfindən verilir 16 mart '14 saat 14:39 'da 2012-03-16 14:39

Swift

Burada və ətrafında StackOverflow var ton və ton şərhlər, amma yalnız iş üçün vacib bir şey tapmaq üçün çalışırıq bir başlanğıc əgər, bu YouTube tutorial seyr cəhd edin (bu mənə nəhayət bunu başa necə kömək).

Məlumatı növbəti görünüşü nəzarətçiyə ötürün

Aşağıda video əsasında bir nümunədir. Fikir, İlk Görünüş Denetleyicisindeki mətn sahəsində simli İkinci Görünüş Denetleyicisindeki etiketə köçürməkdir.

2019

11 авг. cavab Suraqç 11 avqustda verilir . 2015-08-11 09:35 '15 'də saat 09:35' da

MVC-də M model "Model" üçün nəzərdə tutulmuşdur və MVC paradiqmasında model siniflərin rolu proqram məlumatlarını idarə etməkdir. Model görünüşün əksinədir - görünüş məlumatları necə göstərə bilir, lakin məlumatlarla nə ilə məşğul olmağı bilmir, halbuki model məlumatlarla necə işlədiyini bilir, ancaq onu necə göstərmək barədə heç nə öyrənmir. Modellər kompleks ola bilər, amma bunların olması lazım deyil - tətbiqi üçün bir model simli və ya lüğətlərin bir sıra kimi sadə ola bilər.

Kontrolörün rolu görünüş və model arasında vasitəçilik etməkdir. Buna görə də, bir və ya daha çox görüntü obyektlərinə və bir və ya daha çox model obyektinə istinad lazımdır. Deyək ki, sizin modeliniz bir sıra lüğətlərdir, hər bir lüğət sizin masanızdakı bir sıra təmsil edir. Ərizənizin kök görünüşü bu cədvəldə göstərilir və faylın bir dosyanın yüklənməsindən məsul ola bilər. Istifadəçi masaya yeni bir satır əlavə etməyi qərara aldıqda, bir düyməyə basacaq və nəzarətçi yeni (dəyişkən) lüğət yaradır və sətrə əlavə edir. Xətti doldurmaq üçün nəzarətçi detallı görünüşü nəzarətçi yaradır və yeni bir lüğət verir. Ətraflı görünüşlü nəzarətçi lüğətdə doldurur və onu qaytarır. Sözlük artıq modelin bir hissəsidir, buna görə heç bir şey olmur.

119
06 марта '11 в 16:49 2011-03-06 16:49 Cavab Caleb Mart 06 '11 16:49 2011-03-06 16:49 verilir

İOS-də başqa bir sinifdə əldə edilə bilən müxtəlif yollar var. Məsələn,

  • Başqa bir sinif ayırdıqdan sonra birbaşa başlatma.
  • Nümayəndə heyəti - məlumat ötürülməsi üçün
  • Bildiriş - məlumatları bir neçə sinfə bir anda ötürmək
  • NSUserDefaults saxla - daha sonra əldə etmək üçün
  • Subay siniflər
  • Veritabanları və plist kimi digər saxlama mexanizmləri və s.

Amma cari sinifdə paylanan başqa bir sinifə dəyər vermək sadə bir ssenari üçün, ən ümumi və üstünlükli üsul seçimdən sonra dəyərləri birbaşa tənzimləmək olardı. Bu belədir: -

Bunu iki nəzarətçi - Controller1 və Controller2 ilə başa düşə bilərik

Controller1 sinifində bir Controller2 obyekti yaratmaq və ötürülmüş Dize dəyərinə basın. Bunu aşağıdakı kimi aparmaq olar: -

 - (void)pushToController2 { Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil]; [obj passValue:@"String"]; [self pushViewController:obj animated:YES]; } 

Controller2 sinifinin tətbiqində, bu funksiya as-

 @interface Controller2 : NSObject @property (nonatomic , strong) NSString* stringPassed; @end @implementation Controller2 @synthesize stringPassed = _stringPassed; - (void) passValue:(NSString *)value { _stringPassed = value; //or self.stringPassed = value } @end 

Ayrıca, Controller2 sinifinin xüsusiyyətlərini belə birbaşa aşağıdakı kimi təyin edə bilərsiniz:

 - (void)pushToController2 { Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil]; [obj setStringPassed:@"String"]; [self pushViewController:obj animated:YES]; } 

Bir neçə dəyərdən keçmək üçün bir neçə parametrdən istifadə edə bilərsiniz, məsələn: -

 Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil]; [obj passValue:@"String1" andValues:objArray withDate:date]; 

Yoxsa ümumi funksiyaya aid olan üç parametrdən daha çox keçməlisinizsə, nümunə sinifində dəyərləri saxlaya və bu modelObject'i növbəti sinifə keçə bilərsiniz.

 ModelClass *modelObject = [[ModelClass alloc] init]; modelObject.property1 = _property1; modelObject.property2 = _property2; modelObject.property3 = _property3; Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil]; [obj passmodel: modelObject]; 

İstədiyiniz qədər qısa,

 1) set the private variables of the second class initialise the values by calling a custom function and passing the values. 2) setProperties do it by directlyInitialising it using the setter method. 3) pass more that 3-4 values related to each other in some manner , then create a model class and set values to its object and pass the object using any of the above process. 

Bu kömək edir

85
08 апр. Cavab doğum günü 08 apr. 2014-04-08 13:24 '14 at 13:24 2014-04-08 13:24

Əlavə tədqiqatdan sonra protokolların və nümayəndələrin Apple üçün doğru / üstünlük təşkil etdiyinə dair fikirlər oldu.

Bu nümunəni istifadə edərək sona çatdım.

Dispetçerlər və @iPhone Dev SDK digər obyektləri arasında məlumat mübadiləsi

Bu gözəl işlədi və mənim fikirlərim arasında bir simli və array keçirməyə icazə verdi.

Yardımınız üçün təşəkkür edirik.

74
14 марта '11 в 0:20 2011-03-14 00:20 Cavab Matt Price tərəfindən 14 Mart 2011-ci ildə 0:20 2011-03-14 00:20 ilə verilir

Mən itkin bloklarla ən sadə və ən zərif versiyanı tapıram. Qaytarılmış məlumatları "A" kimi gözləyir və görünüş nəzarətçisini "B" kimi qaytarmaq üçün ad kontrolörünə icazə verin. Bu nümunədə biz 2 dəyər almaq istəyirik: Tip1dən birinci və Tip2-dən ikinci.

Storyboard istifadə etdiyimizi düşünsək, ilk nəzarətçi, məsələn, bir seqmentin hazırlanması zamanı geri çağırma blokunu quraşdırır:

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.destinationViewController isKindOfClass:[BViewController class]]) { BViewController *viewController = segue.destinationViewController; viewController.callback = ^(Type1 *value1, Type2 *value2) { // optionally, close B //[self.navigationController popViewControllerAnimated:YES]; // let do some action after with returned values action1(value1); action2(value2); }; } } 

və "B" nəzarətçi geri çağırış əmlakını elan etməlidir, BViewController.h:

 // it is important to use "copy" @property (copy) void(^callback)(Type1 *value1, Type2 *value2); 

BViewController.m tətbiq faylından daha sonra geri çağırışı qaytarmaq üçün istədiyiniz dəyərləri əldə etdikdən sonra, zəng etməliyik:

 if (self.callback) self.callback(value1, value2); 

Xatırlamaq lazım olan bir məqam budur ki, blokun istifadə edilməsi tez-tez burada açıqlanmış olanlar kimi güclü və __ əsrlik əlaqələrin idarə edilməsini tələb edir .

59
14 окт. 14 oktyabrda Leszek Zarna tərəfindən verilən cavab . 2013-10-14 21:11 '13 at 21:11 2013-10-14 21:11

Bir çox cavablar yaxşı məlumatlara malikdir, lakin heç kim bu məsələyə tamamilə toxunmur.

Sual, dispetçerlər arasında məlumatın ötürülməsi ilə bağlı sual verir. Bu xüsusi nümunədə, fikirlər arasında məlumatların ötürülməsi ilə bağlı suallar verilir, lakin iOS üçün özünü müəyyənləşdirən yenilikləri nəzərə alsaq, orijinal poster ehtimalları ViewController arasında nəzərdə tutulur və ViewControllers-də iştirak etmədən keçirilir. Göründüyü kimi, bütün cavablar iki görünüşü nəzarət edənlərə yönəldilmişdir, amma tətbiq informasiya mübadiləsində ikidən çox görünüşü nəzarətçidən istifadə etmək üçün inkişaf edirsə?

Original poster SingletonsAppDelegate-dən istifadə haqqında da soruşdu. Bu suallara cavab verilməlidir.

Hər kəsin bu suala baxmasına kömək etmək üçün, tam cavab istəyənlərə bunu təmin etməyə çalışacağam.

Ərizə skriptləri

Çox hipotetik, mücərrəd müzakirə aparmaq əvəzinə, konkret tətbiqlərə kömək edir. İki nəzarətçi ilə vəziyyəti və nəzarətçiyə ikidən çox baxımdan vəziyyəti müəyyən etmək üçün iki xüsusi tətbiq ssenarisini təyin edəcəyəm.

Birinci ssenarisi: ən çox iki baxış meneceri məlumat mübadiləsini tələb edir. Grafiğin 1-ə baxın.

2019

49
ответ дан Jason Cross 06 апр. '15 в 1:04 2015-04-06 01:04

Существует несколько способов совместного использования данных.

  • Вы всегда можете обмениваться данными с помощью NSUserDefaults . Установите значение, которое вы хотите разделить, по отношению к выбранному вами ключу и получите значение от NSUserDefault , связанное с этим ключом в следующем контроллере представления.

     [[NSUserDefaults standardUserDefaults] setValue:value forKey:key] [[NSUserDefaults standardUserDefaults] objectForKey:key] 
  • Вы можете просто создать свойство в viewcontrollerA . Создайте объект viewcontrollerA в viewcontrollerB и назначьте требуемое значение этому свойству.

  • Вы также можете создавать пользовательские делегаты для этого.

37
ответ дан Anubrata Santra 27 сент. '13 в 13:38 2013-09-27 13:38

Передача данных из ViewController 2 (destination) в viewController 1 (Source) является более интересной. Предполагая, что вы используете storyBoard, это все, что я узнал:

  • Делегат
  • Уведомление
  • Пользовательские настройки по умолчанию
  • Singleton

Те были обсуждены здесь уже.

Я обнаружил, что есть больше способов:

-Использование обратных вызовов блока:

использовать его в методе prepareForSegue в VC1

 NextViewController *destinationVC = (NextViewController *) segue.destinationViewController; [destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC) { self.blockLabel.text = destination.blockTextField.text; }]; 

-Использование раскадровки Unwind (Выход)

Внедрите метод с аргументом UIStoryboardSegue в VC 1, например:

 -(IBAction)UnWindDone:(UIStoryboardSegue *)segue { } 

В окне storyBoard нажмите кнопку "вернуться" на зеленый "Выход" (Unwind) vc. Теперь у вас есть segue, который "возвращается", поэтому вы можете использовать свойство destinationViewController в файле readyForSegue VC2 и измените любое свойство VC1 до его возврата.

  • Другой вариант использования раскадровки Undwind (Exit) - вы можете используйте метод, который вы написали в VC1

     -(IBAction)UnWindDone:(UIStoryboardSegue *)segue { NextViewController *nextViewController = segue.sourceViewController; self.unwindLabel.text = nextViewController.unwindPropertyPass; } 

    И в readyForSegue VC1 вы можете изменить любое свойство, которое хотите разделить.

В обоих вариантах размотки вы можете установить свойство тега кнопки и проверить его в подготовитьForSegue.

Надеюсь, я добавил кое-что к обсуждению.

:) Приветствия.

37
ответ дан Yevgeni 11 апр. '14 в 3:33 2014-04-11 03:33

В OP не упоминались контроллеры представлений, но так много @, что я хотел подслушивать то, что некоторые из новых функций LLVM позволяют сделать это проще, когда вы хотите передавать данные с одного контроллера вида на другой, а затем получить некоторые результаты.

Сегменты раскадровки, блоки ARC и LLVM делают это легче, чем когда-либо для меня. Некоторые ответы выше упомянутых раскадровки и segue уже, но все еще опирались на делегацию. Определение делегатов, безусловно, работает, но некоторым людям легче найти указатели или блоки кода.

С помощью UINavigators и segues есть простые способы передачи информации контроллеру подчиненного и возврату информации. ARC делает простые указатели на вещи, полученные из NSObjects, поэтому, если вы хотите, чтобы подчиненный контроллер добавлял/изменял/модифицировал некоторые данные для вас, передайте ему указатель на изменяемый экземпляр. Блоки упрощают прохождение, поэтому, если вы хотите, чтобы подчиненный контроллер вызывал действие на вашем контроллере более высокого уровня, передайте ему блок. Вы определяете блок, чтобы принять любое количество аргументов, которое имеет смысл для вас. Вы также можете разработать API для использования нескольких блоков, если это лучше всего подходит.

Вот два тривиальных примера клея segue. Первый - это простой показ одного параметра, переданного для ввода, второй для вывода.

 // Prepare the destination view controller by passing it the input we want it to work on // and the results we will look at when the user has navigated back to this controller view. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { [[segue destinationViewController] // This parameter gives the next controller the data it works on. segueHandoffWithInput:self.dataForNextController // This parameter allows the next controller to pass back results // by virtue of both controllers having a pointer to the same object. andResults:self.resultsFromNextController]; } 

Этот второй пример показывает передачу блока обратного вызова для второго аргумента. Мне нравится использовать блоки, потому что он держит соответствующие детали близко друг к другу в источнике - источник более высокого уровня.

 // Prepare the destination view controller by passing it the input we want it to work on // and the callback when it has done its work. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { [[segue destinationViewController] // This parameter gives the next controller the data it works on. segueHandoffWithInput:self.dataForNextController // This parameter allows the next controller to pass back results. resultsBlock:^(id results) { // This callback could be as involved as you like. // It can use Grand Central Dispatch to have work done on another thread for example. [self setResultsFromNextController:results]; }]; } 
35
ответ дан WeakPointer 22 февр. '13 в 1:26 2013-02-22 01:26

Если вы хотите передать данные с одного контроллера на другой, попробуйте этот код

FirstViewController.h

 @property (nonatomic, retain) NSString *str; 

SecondViewController.h

 @property (nonatomic, retain) NSString *str1; 

FirstViewController.m

 - (void)viewDidLoad { // message for the second SecondViewController self.str = @"text message"; [super viewDidLoad]; } -(IBAction)ButtonClicked { SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; secondViewController.str1 = str; [self.navigationController pushViewController:secondViewController animated:YES]; } 
26
ответ дан user2998756 18 нояб. '13 в 15:48 2013-11-18 15:48

Я долго искал это решение, Atlast нашел его. Прежде всего объявите все объекты в файле SecondViewController.h, например

 @interface SecondViewController: UIviewController { NSMutableArray *myAray; CustomObject *object; } 

Теперь в вашем файле реализации выделите память для этих объектов, таких как

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization myAray=[[NSMutableArray alloc] init]; object=[[CustomObject alloc] init]; } return self; } 

Теперь вы выделили память для Array и объекта. теперь вы можете заполнить эту память, прежде чем нажимать эту ViewController

Перейдите в свой SecondViewController.h и напишите два метода

 -(void)setMyArray:(NSArray *)_myArray; -(void)setMyObject:(CustomObject *)_myObject; 

в файле реализации вы можете реализовать функцию

 -(void)setMyArray:(NSArray *)_myArray { [myArra addObjectsFromArray:_myArray]; } -(void)setMyObject:(CustomObject *)_myObject { [object setCustomObject:_myObject]; } 

ожидая, что ваш CustomObject должен иметь с ним функцию setter.

теперь выполняется ваша основная работа. перейдите в то место, где вы хотите нажать SecondViewController , и сделайте следующее:

 SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]] ; [secondView setMyArray:ArrayToPass]; [secondView setMyObject:objectToPass]; [self.navigationController pushViewController:secondView animated:YES ]; 

Соблюдайте орфографические ошибки.

25
ответ дан AsifHabib 27 июля '13 в 11:52 2013-07-27 11:52

Это не способ сделать это, вы должны использовать делегаты, я предполагаю, что у нас есть два диспетчера представлений ViewController1 и ViewController2, и эта вещь проверки находится в первом и когда ее состояние изменяется, вы хотите что-то сделать в ViewController2, чтобы достичь этого правильно, вы должны сделать следующее:

Добавьте новый файл в проект (Objective-C Protocol) File → New, теперь назовите его ViewController1Delegate или что хотите и напишите между директивами @interface и @end

 @optional - (void)checkStateDidChange:(BOOL)checked; 

Теперь перейдите в ViewController2.h и добавьте

 #import "ViewController1Delegate.h" 

затем измените его определение на

 @interface ViewController2: UIViewController<ViewController1Delegate> 

Теперь перейдите в ViewController2.m и внутри реализации добавьте:

 - (void)checkStateDidChange:(BOOL)checked { if (checked) { // Do whatever you want here NSLog(@"Checked"); } else { // Also do whatever you want here NSLog(@"Not checked"); } } 

Теперь перейдите в ViewController1.h и добавьте следующее свойство:

 @property (weak, nonatomic) id<ViewController1Delegate> delegate; 

Теперь, если вы создаете ViewController1 внутри ViewController2 после некоторого события, вы должны сделать это так, используя файлы NIB:

 ViewController1* controller = [[NSBundle mainBundle] loadNibNamed:@"ViewController1" owner:self options:nil][0]; controller.delegate = self; [self presentViewController:controller animated:YES completion:nil]; 

Теперь вы все настроены, всякий раз, когда вы обнаруживаете, что событие проверки было изменено в ViewController1, все, что вам нужно сделать, это ниже

 [delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control 

Скажите, пожалуйста, если что-нибудь, что не понятно, если я правильно не понял ваш вопрос.

21
ответ дан Boda Taljo 01 сент. '14 в 22:46 2014-09-01 22:46

1. Создайте экземпляр первого View Viewer во втором контроллере просмотра и сделайте его свойство @property (nonatomic,assign) .

2. Назначьте экземпляр SecondviewController этого контроллера представления.

2. . Когда вы закончите операцию выбора, скопируйте массив в первый вид контроллера. Когда u выгружает SecondView, FirstView будет хранить данные массива.

Bu kömək edir.

18
ответ дан kaar3k 23 мая '12 в 16:08 2012-05-23 16:08

Если вы хотите отправить данные с одного на другой viewController, вот путь к нему:

Скажем, у нас есть viewControllers: viewControllerA и viewControllerB

Теперь в viewControllerB.h

 @interface viewControllerB : UIViewController { NSString *string; NSArray *array; } - (id)initWithArray:(NSArray)a andString:(NSString)s; 

В viewControllerB.m

 #import "viewControllerB.h" @implementation viewControllerB - (id)initWithArray:(NSArray)a andString:(NSString)s { array = [[NSArray alloc] init]; array = a; string = [[NSString alloc] init]; string = s; } 

В viewControllerA.m

 #import "viewControllerA.h" #import "viewControllerB.h" @implementation viewControllerA - (void)someMethod { someArray = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil]; someString = [NSString stringWithFormat:@"Hahahahaha"]; viewControllerB *vc = [[viewControllerB alloc] initWithArray:someArray andString:someString]; [self.navigationController pushViewController:vc animated:YES]; [vc release]; } 

Таким образом, вы можете передавать данные с viewControllerA в viewControllerB без установки каких-либо делегатов.;)

18
ответ дан Aniruddh Joshi 29 июля '12 в 13:28 2012-07-29 13:28

В настоящее время я участвую в решении с открытым исходным кодом этой проблемы через проект MCViewFactory, который можно найти здесь:

https://github.com/YetiHQ/manticore-iosviewfactory

Идея имитирует парадигму намерений Android, используя глобальный factory, чтобы управлять просмотром, на который вы смотрите, и использовать "намерения" для переключения и передачи данных между представлениями. Вся документация находится на странице github, но вот некоторые основные моменты:

Вы настроите все свои представления в файлах .XIB и зарегистрируете их в делегате приложения, инициализируя factory.

 // Register activities MCViewFactory *factory = [MCViewFactory sharedFactory]; // the following two lines are optional. [factory registerView:@"YourSectionViewController"]; 

Теперь, в вашем VC, в любое время, когда вы хотите перейти на новый VC и передать данные, вы создаете новое намерение и добавляете данные в свой словарь (savedInstanceState). Затем просто установите текущую цель factory:

 MCIntent* intent = [MCIntent intentWithSectionName:@"YourSectionViewController"]; [intent setAnimationStyle:UIViewAnimationOptionTransitionFlipFromLeft]; [[intent savedInstanceState] setObject:@"someValue" forKey:@"yourKey"]; [[intent savedInstanceState] setObject:@"anotherValue" forKey:@"anotherKey"]; // ... [[MCViewModel sharedModel] setCurrentSection:intent]; 

Все ваши представления, которые соответствуют этому, должны быть подклассами MCViewController, которые позволяют вам переопределить новый метод onResume:, позволяющий вам получить доступ к переданным вами данным.

 -(void)onResume:(MCIntent *)intent { NSObject* someValue = [intent.savedInstanceState objectForKey:@"yourKey"]; NSObject* anotherValue = [intent.savedInstanceState objectForKey:@"anotherKey"]; // ... // ensure the following line is called, especially for MCSectionViewController [super onResume:intent]; } 

Надеюсь, что некоторые из вас считают это решение полезным/интересным.

16
ответ дан user2563044 16 сент. '14 в 20:18 2014-09-16 20:18

Передача данных между FirstViewController и SecondViewController ниже

Məsələn:

Значение строки FirstViewController как

 StrFirstValue = @"first"; 

поэтому мы можем передать это значение во втором классе, используя следующий шаг

1 > Нам нужно вырезать строковый объект в файле SecondViewController.h

 NSString *strValue; 

2 > Необходимо объявить свойство, как показано ниже, в файле .h.

 @property (strong, nonatomic) NSString *strSecondValue; 

3 > Нужно синтезировать это значение в файле FirstViewController.m ниже объявления заголовка

 @synthesize strValue; 

и в FirstViewController.h:

 @property (strong, nonatomic) NSString *strValue; 

4 > В FirstViewController, из которого мы переходим ко второму виду, напишите ниже код в этом методе.

 SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]]; [secondView setStrSecondValue:StrFirstValue]; [self.navigationController pushViewController:secondView animated:YES ]; 
16
ответ дан Chris Alan 23 окт. '13 в 13:58 2013-10-23 13:58

В моем случае я использовал одноэлементный класс, который может работать как глобальный объект, позволяющий получать доступ к данным почти везде в приложении. Прежде всего, нужно построить одноэлементный класс. Пожалуйста, обратитесь к странице, Каким должен быть мой Objective-C синглтон? " И то, что я сделал, чтобы сделать объект глобально доступным, просто импортировал его в appName_Prefix.pch , который предназначен для применения оператора импорта в каждом классе. Чтобы получить доступ к этому объекту и использовать его, я просто внедрил метод класса для возврата общего экземпляра, который содержит свои собственные переменные

14
ответ дан petershine 06 марта '11 в 17:03 2011-03-06 17:03

Создайте свойство в следующем view controller .h и определите getter и setter.

Добавьте это property в NextVC.h на nextVC

 @property (strong, nonatomic) NSString *indexNumber; 

Əlavə etmək üçün

@synthesize indexNumber; в NextVC.m

И последний

 NextVC *vc=[[NextVC alloc]init]; vc.indexNumber=@"123"; [self.navigationController vc animated:YES]; 
13
ответ дан Vivek Yadav 02 янв. '14 в 15:29 2014-01-02 15:29

Я знаю, что это избитая тема, но для тех, кто хочет ответить на этот вопрос с помощью SWIFT-косы и хочет пример с голубыми костями, вот мой метод go-to для передачи данных, если вы используете segue, чтобы обойти.

Это похоже на выше, но без кнопок, меток и т.д. Просто передавайте данные из одного представления в другое.

Настройка раскадровки

Есть три части.

  • Отправитель
  • The Segue
  • Получатель

Это очень простой макет представления с разделом между ними.


2019

ответ дан Christopher Wade Cantley 25 авг. '15 в 18:28 2015-08-25 18:28

Есть много способов сделать это, и важно выбрать правильный. Вероятно, одним из самых больших архитектурных решений является то, как код модели будет доступен или доступен во всем приложении.

Я написал сообщение в блоге об этом некоторое время назад: Совместное использование кода модели . Вот краткое резюме:

Общие данные

Один из подходов - обмениваться указателями на объекты модели между контроллерами представлений.

  • Итерация грубой силы на контроллерах представлений (в панели навигации или панели управления таблицами) для установки данных
  • Установите данные в prepareForSegue (если раскадровки) или init (если программно)

Поскольку подготовка к segue является наиболее распространенной, вот пример:

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { var next = segue.destinationViewController as NextViewController next.dataSource = dataSource } 

Независимый доступ

Другой подход заключается в том, чтобы обрабатывать экран, полный данных за один раз, и вместо того, чтобы связывать контроллеры представлений друг с другом, каждая из контроллеров представления с одним источником данных, который они могут получить независимо.

Самый распространенный способ, которым я видел это, - это одиночный экземпляр. Поэтому, если ваш объект singleton был DataAccess вы можете сделать следующее в методе viewDidLoad UIViewController:

 func viewDidLoad() { super.viewDidLoad() var data = dataAccess.requestData() } 

Существуют дополнительные инструменты, которые также помогают передавать данные:

  • Наблюдение за ключевым значением
  • NSNotification
  • Основные данные
  • NSFetchedResultsController
  • Источник данных

Основные данные

Хорошая вещь в Core Data заключается в том, что она имеет обратные отношения. Поэтому, если вы хотите просто предоставить NotesViewController объект заметок, который вы можете использовать, поскольку он будет иметь обратную связь с чем-то другим, например, с ноутбуком. Если вам нужны данные в записной книжке в NotesViewController, вы можете вернуться к графику объекта, выполнив следующие действия:

 let notebookName = note.notebook.name 

Подробнее об этом читайте в моем блоге: общий код модели

10
ответ дан Korey Hinton 29 янв. '15 в 20:35 2015-01-29 20:35

Вы можете сохранить данные в делегате приложения, чтобы получить доступ к ним через контроллеры представлений в своем приложении. Все, что вам нужно сделать, это создать общий экземпляр делегата приложения

 AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; 

Misal

если вы объявляете NSArray object *arrayXYZ , тогда вы можете получить к нему доступ в любом контроллере просмотра appDelegate.arrayXYZ

10
ответ дан ak_tyagi 29 мая '15 в 15:34 2015-05-29 15:34

если вы хотите передать данные из ViewControlerOne в ViewControllerTwo, попробуйте эти.

Сделайте это в ViewControlerOne.h

  @property (nonatomic, strong) NSString *str1; 

Сделайте это в ViewControllerTwo.h

  @property (nonatomic, strong) NSString *str2; 

Синтезировать str2 в ViewControllerTwo.m

 @interface ViewControllerTwo () @end @implementation ViewControllerTwo @synthesize str2; 

Сделайте это в ViewControlerOne.m

  - (void)viewDidLoad { [super viewDidLoad]; // Data or string you wants to pass in ViewControllerTwo.. self.str1 = @"hello world"; } 

на кнопке click event сделать это.

 -(IBAction)ButtonClicked { //Navigation on buttons click event from ViewControlerOne to ViewControlerTwo with transferring data or string.. ViewControllerTwo *objViewTwo=[self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerTwo"]; obj.str2=str1; [self.navigationController pushViewController: objViewTwo animated:YES]; } 

сделать это в ViewControllerTwo.m

 - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%@",str2); } 
10
ответ дан krushnsinh 27 мая '15 в 17:11 2015-05-27 17:11

NewsViewController

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tbl_View deselectRowAtIndexPath:indexPath animated:YES]; News *newsObj = [newstitleArr objectAtIndex:indexPath.row]; NewsDetailViewController *newsDetailView = [[NewsDetailViewController alloc] initWithNibName:@"NewsDetailViewController" bundle:nil]; newsDetailView.newsHeadlineStr = newsObj.newsHeadline; [self.navigationController pushViewController:newsDetailView animated:YES]; } 

NewsDetailViewController.h

 @interface NewsDetailViewController : UIViewController @property(nonatomic,retain) NSString *newsHeadlineStr; @end 

NewsDetailViewController.m

 @synthesize newsHeadlineStr; 
10
ответ дан Mohsin Sabasara 24 окт. '13 в 15:07 2013-10-24 15:07

Делегирование - единственное решение для выполнения таких операций, когда вы используете .xib файлы, однако все ответы, описанные выше, для storyboard для .xibs файлов, вам нужно использовать делегирование. это единственное решение, которое вы можете.

Другим решением является использование singleton class pattern, инициализирующее его один раз и использование его во всем приложении.

10
ответ дан user2786888 17 сент. '13 в 12:10 2013-09-17 12:10

Если вы хотите отправить данные с одного на другой viewController, вот путь к нему:

Скажем, у нас есть viewControllers: ViewController и NewViewController.

в ViewController.h

 #import <UIKit/UIKit.h> @interface ViewController : UIViewController { IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4; } @property (nonatomic,retain) IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4; -(IBAction)goToNextScreen:(id)sender; @end 

в ViewController.m

 #import "ViewController.h" #import "NewViewController.h" @implementation ViewController @synthesize mytext1,mytext2,mytext3,mytext4; -(IBAction)goToNextScreen:(id)sender { NSArray *arr = [NSArray arrayWithObjects:mytext1.text,mytext2.text,mytext3.text,mytext4.text, nil]; NewViewController *newVc = [[NewViewController alloc] initWithNibName:@"NewViewController" bundle:nil]; newVc.arrayList = arr; [self.navigationController pushViewController:newVc animated:YES]; } 

В NewViewController.h

 #import <UIKit/UIKit.h> @interface NewViewController : UITableViewController { NSArray *arrayList; NSString *name,*age,*dob,*mobile; } @property(nonatomic, retain)NSArray *arrayList; @end 

В NewViewController.m

 #import "NewViewController.h" #import "ViewController.h" @implementation NewViewController @synthesize arrayList; #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [arrayList count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } // Configure the cell... cell.textLabel.text = [arrayList objectAtIndex:indexPath.row]; return cell; } @end 

Таким образом, мы можем передавать данные с одного диспетчера представлений на другой контроллер представления...

8
ответ дан Sabs 05 авг. '13 в 7:49 2013-08-05 07:49

Мне нравится идея объектов модели и объектов Mock на основе NSProxy для фиксации или удаления данных, если пользовательский выбор может быть отменен.

Легко передавать данные, поскольку это один объект или пара объектов, и если вы позволили использовать контроллер UINavigationController, вы можете сохранить ссылку на модель внутри, и все нажатые контроллеры представлений могут получить к ней доступ непосредственно от контроллера навигации.

8
ответ дан highmaintenance 08 мая '14 в 19:09 2014-05-08 19:09

Я видел много людей, которые усложняли это, используя метод didSelectRowAtPath . Я использую Core Data в моем примере.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ //this solution is for using Core Data YourCDEntityName * value = (YourCDEntityName *)[[self fetchedResultsController] objectAtIndexPath: indexPath]; YourSecondViewController * details = [self.storyboard instantiateViewControllerWithIdentifier:@"nameOfYourSecondVC"];//make sure in storyboards you give your second VC an identifier //Make sure you declare your value in the second view controller details.selectedValue = value; //Now that you have said to pass value all you need to do is change views [self.navigationController pushViewController: details animated:YES]; } 

4 строки кода внутри метода, и все готово.

7
ответ дан App Dev Guy 16 янв. '15 в 6:18 2015-01-16 06:18

Это действительно замечательный tutorial для всех, кто этого хочет. Burada nümunə kodu:

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"myIdentifer]) { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; myViewController *destViewController = segue.destinationViewController; destViewController.name = [object objectAtIndex:indexPath.row]; } } 
3
ответ дан crazy_tiger_corp 28 сент. '15 в 12:00 2015-09-28 12:00

Есть много @ на эти вопросы, предлагающие множество различных способов взаимодействия с диспетчером диспетчера сообщений, которые действительно работают, но я не вижу нигде не упомянутых, какие из них лучше всего использовать и какие из них следует избегать.

На практике, на мой взгляд, рекомендуется только несколько решений:

  • Для передачи данных вперед:
    • переопределить метод prepare(for:sender:) UIViewController при использовании раскадровки и segues
    • передавать данные через инициализатор или через свойства при выполнении переходов контроллера просмотра с кодом
  • Для передачи данных назад
    • обновить состояние совместного использования приложения (которое вы можете передать между контроллерами представлений одним из указанных выше методов)
    • использовать делегацию
    • использовать размотку segue

Решения Я рекомендую НЕ использовать:

  • Ссылка на предыдущий контроллер напрямую, вместо делегирования
  • Обмен данными через однострочный
  • Передача данных через делегат приложения
  • Обмен данными через пользовательские настройки по умолчанию
  • Передача данных через уведомления

Эти решения, хотя и работают в краткосрочной перспективе, вводят слишком много зависимостей, которые будут искажать архитектуру приложения и впоследствии создавать больше проблем.

Для тех, кого это интересует, я написал несколько статей, которые более подробно затрагивают эти моменты и выделяют различные недостатки:

3
ответ дан Matteo Manferdini 03 дек. '16 в 18:27 2016-12-03 18:27
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос