Это не работает, но я работал над простым сервером PhantomJS для Heorku , который будет анализировать любой клиентский JS. Я использую его специально для Angular и Rails для подачи HTML-запросов на бот.
Этот вопрос, кажется, очень популярен здесь в stackoverflow, поэтому я решил попробовать и дать лучший ответ, чтобы помочь людям, начинающим в мире iOS, как я.
Надеюсь, что этот ответ ясен
Передача данных вперед
Передача данных в контроллер просмотра с другого контроллера. Вы должны использовать этот метод, если хотите передать объект / значение с одного контроллера вида на другой контроллер представления, который вы можете нажать в стек навигации.
В этом примере мы будем иметь ViewControllerA
и ViewControllerB
Чтобы передать значение BOOL
с ViewControllerA
на ViewControllerB
, мы сделали бы следующее.
ViewControllerB.h
создать свойство для BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
ViewControllerA
вам нужно рассказать об этом ViewControllerB
, поэтому используйте #import "ViewControllerB.h"
Затем, где вы хотите загрузить представление, например. didSelectRowAtIndex
или несколько IBAction
вам нужно установить свойство в ViewControllerB
, прежде чем вы нажмете его на стек навигатора. ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.isSomethingEnabled = YES;
[self pushViewController:viewControllerB animated:YES];
Это установит isSomethingEnabled
в значение ViewControllerB
на BOOL
значение YES
. Передача данных вперед с помощью Segues
Если вы используете раскадровки вы, скорее всего, используете segues и будете нуждаться в этой процедуре для передачи данных вперед. Это похоже на приведенное выше, но вместо передачи данных перед тем, как вы нажимаете контроллер вида, вы используете метод, называемый
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
. Итак, чтобы передать BOOL
с ViewControllerA
на ViewControllerB
, мы выполнил бы следующее:
ViewControllerB.h
создать свойство для BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
ViewControllerA
, вам нужно рассказать об этом ViewControllerB
поэтому используйте #import "ViewControllerB.h"
ViewControllerA
до ViewControllerB
на раскадровке и дайте ему идентификатор, в этом примере мы будем называть его "showDetailSegue"
ViewControllerA
, который вызывается, когда выполняется какой-либо segue, из-за этого нам нужно определить, какой вызов был вызван, а затем что-то сделать. В нашем примере мы проверим "showDetailSegue"
, и если это будет выполнено, мы передадим наше значение BOOL
в ViewControllerB
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
controller.isSomethingEnabled = YES;
}
}
. Если у вас есть свои представления, встроенные в контроллер навигации, вам нужно немного изменить метод выше на следующие -(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;
}
}
Это установит isSomethingEnabled
в ViewControllerB
на значение BOOL
YES
. Передача данных Назад
Чтобы передать данные с ViewControllerB
] до ViewControllerA
вам нужно использовать Protocols and Delegates или Blocks , последний может использоваться как слабо связанный механизм для обратных вызовов.
To сделаем это, мы сделаем ViewControllerA
делегатом из ViewControllerB
. Это позволяет ViewControllerB
отправить сообщение обратно на ViewControllerA
, чтобы мы могли отправить данные назад.
Чтобы ViewControllerA
был делегатом ViewControllerB
, он должен соответствовать протоколу ViewControllerB
, который мы должны указать. Это указывает ViewControllerA
, какие методы он должен реализовать.
ViewControllerB.h
ниже #import
, но выше @interface
вы указываете протокол. @class ViewControllerB;
@protocol ViewControllerBDelegate <NSObject>
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
@end
ViewControllerB.h
вам нужно настроить свойство delegate
и синтезировать в ViewControllerB.m
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
ViewControllerB
мы вызываем сообщение на delegate
, когда мы выходим на контроллер вида. NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
ViewControllerB
. Теперь в ViewControllerA.h
скажите ViewControllerA
, чтобы импортировать ViewControllerB
и соответствовать его протоколу. #import "ViewControllerB.h"
@interface ViewControllerA : UIViewController <ViewControllerBDelegate>
ViewControllerA.m
реализуем следующий метод из нашего протокола - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(@"This was returned from ViewControllerB %@",item);
}
viewControllerB
в стек навигации нам нужно сообщить ViewControllerB
, что ViewControllerA
является его делегатом, иначе мы получим сообщение об ошибке. ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate = self
[[self navigationController] pushViewController:viewControllerB animated:YES];
Существуют различные способы, с помощью которых данные могут быть получены в другом классе в iOS. Например,
NSUserDefaults
- для доступа к нему позже Но для простого сценария передачи значения другому классу, распределение которого выполняется в текущем классе, наиболее распространенным и предпочтительным методом будет прямая настройка значений после выделения. Это делается следующим образом: -
Мы можем понять это с помощью двух контроллеров - Controller1 и Controller2
Предположим, что в классе Controller1 вы хотите создать объект Controller2 и нажать его со значением String передается. Это можно сделать следующим образом: -
- (void)pushToController2 {
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passValue:@"String"];
[self pushViewController:obj animated:YES];
}
В реализации класса Controller2 будет существовать эта функция 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
. Вы также можете прямо установить свойства класс Controller2 аналогичным образом:
- (void)pushToController2 {
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj setStringPassed:@"String"];
[self pushViewController:obj animated:YES];
}
Чтобы передать несколько значений, вы можете использовать несколько параметров, таких как: -
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passValue:@“String1” andValues:objArray withDate:date];
Или если вам нужно пройти больше чем 3 параметра, которые связаны с общей функцией, вы можете сохранить значения в классе Model и передать этот объект modelObject следующему классу
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];
Итак, если вы хотите -
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.
Надеюсь, это поможет
Передача данных из ViewController 2 (destination) в viewController 1 (Source) является более интересной. Предполагая, что вы используете storyBoard, это все, что я узнал:
Те были обсуждены здесь уже.
Я обнаружил, что существует больше способов:
-Использование обратных вызовов блоков:
use это в методе prepareForSegue
в VC1
NextViewController *destinationVC = (NextViewController *) segue.destinationViewController;
[destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC)
{
self.blockLabel.text = destination.blockTextField.text;
}];
-Использование раскадровки Unwind (Exit)
Внедрить метод с аргументом UIStoryboardSegue в VC 1, как этот:
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue { }
В окне storyBoard нажмите кнопку «вернуться» к зеленой кнопке «Выход» («Разморозь») vc. Теперь у вас есть segue, который «возвращается», поэтому вы можете использовать свойство destinationViewController в файле readyForSegue of VC2 и изменить любое свойство VC1 до его возврата.
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
NextViewController *nextViewController = segue.sourceViewController;
self.unwindLabel.text = nextViewController.unwindPropertyPass;
}
. И в prepareForSegue of VC1 вы можете изменить любое свойство, которое хотите разделить. В обоих вариантах размотки вы можете установить тег свойства кнопки и проверить его в prepareForSegue.
Надеюсь, я добавил что-то к обсуждению.
:) Приветствия.
Если вы хотите отправлять данные от одного к другому 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 без установки любого делегата. ;)
Я видел много людей, которые усложняли это, используя метод 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 строки кода внутри метода, и все готово.
Существует несколько способов совместного использования данных.
NSUserDefaults
. Задайте значение, которое вы хотите использовать, по отношению к выбранному вами ключу, и получите значение из NSUserDefault
, связанное с этим ключом в следующем контроллере представления. [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]
[[NSUserDefaults standardUserDefaults] objectForKey:key]
viewcontrollerA
. Создайте объект viewcontrollerA
в viewcontrollerB
и назначьте это значение этому свойству. Это не способ сделать это, вы должны использовать делегатов, я предполагаю, что у нас есть два контроллера вида 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 и внутри реализации add:
- (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
Пожалуйста, скажите мне, есть ли что-то, что не ясно, если я не понял ваш вопрос правильно.
M в MVC для «Модели», а в парадигме MVC роль классов моделей заключается в управлении данными программы. Модель противоположна представлению - представление знает, как отображать данные, но ничего не знает о том, что делать с данными, тогда как модель знает все о том, как работать с данными, но ничего о том, как ее отображать. Модели могут быть сложными, но они не обязательно должны быть - модель для вашего приложения может быть такой же простой, как массив строк или словарей.
Роль контроллера заключается в посредничестве между представлением и модель. Поэтому им нужна ссылка на один или несколько объектов вида и один или несколько объектов модели. Предположим, что ваша модель представляет собой массив словарей, причем каждый словарь представляет одну строку в вашей таблице. Корневой вид для вашего приложения отображает эту таблицу, и он может отвечать за загрузку массива из файла. Когда пользователь решает добавить новую строку в таблицу, они нажимают какую-то кнопку, и ваш контроллер создает новый (изменяемый) словарь и добавляет его в массив. Чтобы заполнить строку, контроллер создает контроллер подробного представления и дает ему новый словарь. Контроллер подробного представления заполняет словарь и возвращает его. Словарь уже является частью модели, поэтому ничего не должно произойти.
Я знаю, что это избитый предмет, но для тех, кто хочет ответить на этот вопрос с наклоном SWIFT и хочет пример с голубыми костями, вот мой метод go-to для передачи данных, если вы используете segue, чтобы обойти.
Это похоже на вышесказанное, но без кнопок, меток и т. д. Просто передавайте данные с одного вида на другой.
Настройка Раскадровка
Есть три части.
Это очень простой макет представления с segue между ними.
Вот настройка для отправителя
Вот настройка приемника.
Наконец, настройка для сеанса.
Контроллеры просмотра
Мы придерживаемся этого простого поэтому никаких кнопок, а не действий, мы просто перемещаем данные от отправителя к получателю, когда приложение загружается, а затем выводит переданное значение на консоль.
Эта страница берет первоначально загруженное значение и передает его .
//
// ViewControllerSender.swift
// PassDataBetweenViews
//
// Created by Chris Cantley on 8/25/15.
// Copyright (c) 2015 Chris Cantley. All rights reserved.
//
import UIKit
class ViewControllerSender: UIViewController {
// THE STUFF - put some info into a variable
let favoriteMovie = "Ghost Busters"
override func viewDidAppear(animated: Bool) {
// PASS IDENTIFIER - go to the recieving view controller.
self.performSegueWithIdentifier("goToReciever", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//GET REFERENCE - ...to the receiver view.
var viewControllerReceiver = segue.destinationViewController as? ViewControllerReceiver
//PASS STUFF - pass the variable along to the target.
viewControllerReceiver!.yourFavMovie = self.favoriteMovie
}
}
Эта страница просто отправляет значение переменной на консоль при ее загрузке. К этому моменту наш любимый фильм должен быть в этой переменной.
//
// ViewControllerReceiver.swift
// PassDataBetweenViews
//
// Created by Chris Cantley on 8/25/15.
// Copyright (c) 2015 Chris Cantley. All rights reserved.
//
import UIKit
class ViewControllerReceiver: UIViewController {
//Basic empty variable waiting for you to pass in your fantastic favorite movie.
var yourFavMovie = ""
override func viewDidLoad() {
super.viewDidLoad()
//And now we can view it in the console.
println("The Movie is \(self.yourFavMovie)")
}
}
Вот как вы можете справиться с этим, если хотите использовать segue, и у вас нет страниц под навигационным контроллером.
После запуска он должен автоматически переключиться на вид приемника и передать значение от отправителя в приемник, отображая значение в консоли.
В моем случае я использовал одноэлементный класс, который может работать как глобальный объект, позволяющий получать доступ к данным почти везде в приложении. Прежде всего, нужно построить одноэлементный класс. Пожалуйста, обратитесь к странице, «. Как выглядит мой сингл Objective-C? « И то, что я сделал, чтобы сделать объект глобально доступным, просто импортировал его в appName_Prefix.pch
, который предназначен для применения оператора импорта в все классы. Чтобы получить доступ к этому объекту и использовать его, я просто применил метод класса для возврата общего экземпляра, который содержит свои собственные переменные
Это действительно замечательный учебник для тех, кто его хочет. Вот пример кода:
- (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];
}
}
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;
Мне нравится идея объектов модели и Mock-объектов на основе NSProxy для фиксации или удаления данных, если пользовательский выбор может быть отменен.
Легко передавать данные, поскольку это один объект или пара объектов, и если вы скажете UINavigationController-контроллер, вы можете сохранить ссылку на модель внутри, и все нажатые контроллеры представлений могут получить к ней доступ непосредственно от контроллера навигации .
Делегирование - единственное решение для выполнения таких операций, когда вы используете .xib-файлы, однако все описанные выше ответы предназначены для storyboard
для .xibs-файлов, которые необходимо использовать для делегирования. это единственное решение, которое вы можете.
Другим решением является использование singleton class pattern, инициализирующее его один раз и использование его во всем приложении.
После дальнейших исследований казалось, что протоколы и делегаты являются правильными / предпочтительными для Apple способами.
В итоге я использовал этот пример
Обмен данными между представлениями контроллеры и другие объекты @ iPhone Dev SDK
Работал отлично и разрешил мне передавать строку и массив вперед и назад между моими представлениями.
Спасибо за вашу помощь
, если вы хотите передать данные из 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);
}
Я нахожу простейшую и самую элегантную версию с прохождением блоков. Давайте назовите контроллер вида, который ожидает возвращенных данных как «A» и возвращает контроллер представления как «B». В этом примере мы хотим получить 2 значения: первый из Type1 и второй из Type2.
Предполагая, что мы используем Storyboard, первый контроллер устанавливает блок обратного вызова, например, во время подготовки segue:
- (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's do some action after with returned values
action1(value1);
action2(value2);
};
}
}
и «B» должны объявить свойство обратного вызова, BViewController.h:
// it is important to use "copy"
@property (copy) void(^callback)(Type1 *value1, Type2 *value2);
Чем в файле реализации BViewController.m после того, как мы получим желаемые значения для возврата нашего обратного вызова, следует вызвать:
if (self.callback)
self.callback(value1, value2);
Следует помнить, что использование блока часто требует управления сильными и __вековыми ссылками, например здесь
Есть много ответов на эти вопросы, предлагающие множество различных способов взаимодействия с диспетчером диспетчера сообщений, которые действительно будут работать, но я не вижу нигде не упомянутых, какие из них лучше всего использовать и какие из них следует избегать.
prepare(for:sender:)
в UIViewController
при использовании раскадровки и segues передавать данные через инициализатор или через свойства при выполнении переходов контроллера просмотра, т. е. код Эти решения, хотя и работают в краткосрочной перспективе, вводят слишком много зависимостей, которые будут искажать архитектуру приложения и создавать больше проблем позже.
Для тех, кого это интересует, я написал несколько статей, которые более подробно затрагивают эти моменты и выделяют различные недостатки:
Я долго искал это решение, 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 ];
Позаботьтесь о орфографических ошибках.
Если вы хотите передавать данные с одного контроллера на другой, попробуйте этот код
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];
}
Если вы хотите отправлять данные от одного к другому 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
Таким образом, мы можем передавать данные с одного диспетчера представлений на другой контроллер представления ...
Вы можете сохранить данные в делегате приложения, чтобы получить доступ к ним через контроллеры представлений в своем приложении. Все, что вам нужно сделать, это создать общий экземпляр делегата приложения
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
. Для примера
, если вы объявите NSArray object *arrayXYZ
, вы можете получить к нему доступ в любом контроллере представления appDelegate.arrayXYZ
Создайте свойство на следующем view controller .h
и определите getter и setter.
Добавьте это property
в NextVC.h на nextVC
@property (strong, nonatomic) NSString *indexNumber;
Добавить
@synthesize indexNumber;
в NextVC.m
И последний
NextVC *vc=[[NextVC alloc]init];
vc.indexNumber=@"123";
[self.navigationController vc animated:YES];
Передача данных между FirstViewController в SecondViewController, как показано ниже
Например:
Значение FirstViewController String как
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 ];
Существует множество способов сделать это, и важно выбрать правильный. Вероятно, одним из самых больших архитектурных решений является то, как код модели будет доступен или доступен во всем приложении.
Я написал сообщение в блоге об этом некоторое время назад: Общий код модели , Ниже приведен краткий обзор:
. Один из подходов состоит в том, чтобы совместно использовать указатели на объекты модели между контроллерами представления.
Поскольку подготовка к segue является наиболее распространенной, здесь приведен пример:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var next = segue.destinationViewController as NextViewController
next.dataSource = dataSource
}
Другой подход заключается в том, чтобы обрабатывать полный экран данных одновременно, и вместо того, чтобы связывать контроллеры представлений друг с другом, каждый из них контролирует один источник данных, который они могут получить независимо.
Наиболее распространенный способ, которым я видел это, - это экземпляр singleton . Поэтому, если ваш объект singleton был DataAccess
, вы можете сделать следующее в методе viewDidLoad для UIViewController:
func viewDidLoad() {
super.viewDidLoad()
var data = dataAccess.requestData()
}
. Существуют дополнительные инструменты, которые также помогают передавать данные:
Хорошая вещь в Core Data заключается в том, что она имеет обратные отношения. Поэтому, если вы хотите просто предоставить NotesViewController объект заметок, который вы можете использовать, поскольку он будет иметь обратную связь с чем-то другим, например, с ноутбуком. Если вам нужны данные на ноутбуке в NotesViewController, вы можете вернуться к графику объекта, выполнив следующие действия:
let notebookName = note.notebook.name
Подробнее об этом читайте в моем сообщении в блоге: Общий код модели
Есть тонны и тонны объяснений здесь и вокруг StackOverflow, но если вы новичок, просто пытающийся получить что-то основное для работы, попробуйте посмотреть этот учебник YouTube (это помогло мне, наконец, понять, как это сделать).
Ниже приведен пример, основанный на видео. Идея состоит в том, чтобы передать строку из текстового поля в First View Controller на метку в Second View Controller.
Создать раскладку раскладки в Interface Builder.
First View Controller
Код для первого контроллера просмотра -
import UIKit
class FirstViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
// This function is called before the segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// get a reference to the second view controller
let secondViewController = segue.destination as! SecondViewController
// set a variable in the second view controller with the String to pass
secondViewController.receivedString = textField.text!
}
}
Контроллер второго взгляда
И код для второго контроллера просмотра -
import UIKit
class SecondViewController: UIViewController {
@IBOutlet weak var label: UILabel!
// This variable will hold the data being passed from the First View Controller
var receivedString = ""
override func viewDidLoad() {
super.viewDidLoad()
// Used the text from the First View Controller to set the label
label.text = receivedString
}
}
Не забывайте
UILabel
. Чтобы передать данные с второго контроллера представления на первый контроллер представления, вы используете протокол и делегат . Этот видеоролик - очень четкая прогулка по этому процессу:
Ниже приведен пример, основанный на видео (с некоторыми изменениями).
Создайте раскладной план в Interface Builder. Опять же, чтобы сделать segue, вы просто управляете перетаскиванием с кнопки на второй контроллер просмотра. Установите идентификатор segue на showSecondViewController
. Кроме того, не забудьте подключить выходы и действия, используя имена в следующем коде.
First View Controller
Код для первого контроллера просмотра -
import UIKit
class FirstViewController: UIViewController, DataEnteredDelegate {
@IBOutlet weak var label: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destination as! SecondViewController
secondViewController.delegate = self
}
}
func userDidEnterInformation(info: String) {
label.text = info
}
}
Обратите внимание на использование нашего пользовательского протокола DataEnteredDelegate
.
Второй просмотр контроллера и протокола
Код для второго контроллера просмотра -
import UIKit
// 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? = nil
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: AnyObject) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(info: textField.text!)
// go back to the previous view controller
_ = self.navigationController?.popViewController(animated: true)
}
}
Обратите внимание, что protocol
находится вне класса View Controller.
Вот и все. Запустив приложение, вы сможете отправлять данные с второго контроллера представления на первый.
secondViewController.delegate = self
означает «я согласен быть работником босса». См. этот ответ для другого примера и более подробного объяснения.
– Suragch
26 September 2016 в 06:44
В настоящее время я вношу свой вклад в решение этой проблемы с открытым исходным кодом с помощью проекта MCViewFactory, который можно найти здесь:
https://github.com/YetiHQ/manticore-iosviewfactory
Идея имитирует парадигму намерений Android, используя глобальную фабрику для управления просмотром, на который вы смотрите, и используя «намерения» для переключения и передачи данных между представлениями. Вся документация находится на странице github, но вот некоторые основные моменты:
Вы настраиваете все свои представления в файлах .XIB и регистрируете их в делегате приложения при инициализации фабрики.
// Register activities
MCViewFactory *factory = [MCViewFactory sharedFactory];
// the following two lines are optional.
[factory registerView:@"YourSectionViewController"];
Теперь, в вашем VC, в любое время, когда вы хотите перейти на новый VC и передать данные, вы создаете новое намерение и добавляете данные в свой словарь (savedInstanceState). Затем просто установите текущее намерение фабрики:
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];
}
Надеюсь, что некоторые из вас считают это решение полезным / интересным.
В 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's 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];
}];
}
@property (nonatomic,assign)
. 2. Назначьте экземпляр SecondviewController
этого контроллера вида.
2. Когда вы закончите операцию выбора, скопируйте массив в первый вид контроллера, Когда u выгрузит SecondView, FirstView будет хранить данные массива.
Надеюсь, что это поможет.
@class ViewControllerB;
над определением @protocol? Без этого я получаю «Ожидаемый тип». ошибка в ViewControllerB в строке:- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
в объявлении@protocol
– alan-p 30 August 2012 в 14:16NavigationController
, вы должны использовать[self.navigationController pushViewController:viewController animated:YES];
вместо[self pushViewController:viewControllerB animated:YES];
– Nazir 5 June 2014 в 06:26