Этот поток сделал меня freak, так как мы используем колонки TIMESTAMP
с On UPDATE CURRENT_TIMESTAMP
(т. е. recordTimestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) для отслеживания измененных записей и ETL в хранилище данных.
В случае, если кому-то интересно, в этом case TIMESTAMP
ведут себя правильно, и вы можете различать две аналогичные даты, преобразуя TIMESTAMP
в временную метку unix:
select TestFact.*, UNIX_TIMESTAMP(recordTimestamp) from TestFact;
id recordTimestamp UNIX_TIMESTAMP(recordTimestamp)
1 2012-11-04 01:00:10.0 1352005210
2 2012-11-04 01:00:10.0 1352008810
Этот вопрос, кажется, очень популярен здесь, на 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
.
Передача данных с использованием сегментов
Если вы используете раскадровки, вы, скорее всего, используете сегменты и вам понадобится эта процедура для передачи данных. Это похоже на приведенное выше, но вместо передачи данных перед тем, как нажать контроллер представления, вы используете метод, называемый
-(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
, который вызывается при выполнении любого перехода, из-за этого нам нужно определить, какой вызов был вызван а затем сделай что-нибудь В нашем примере мы проверим "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
необходимо использовать Протоколы и делегаты или Блоки , последний может быть использован как слабосвязанный механизм для обратных вызовов.
Для этого мы сделаем 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];
Центр уведомлений NSN Это еще один способ передачи данных.
// 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];
Передача данных обратно из одного класса в другой (классом может быть любой контроллер, менеджер сети / сеанса, подкласс UIView или любой другой класс)
Блоки являются анонимными функциями.
Этот пример передает данные от Контроллера B к Контроллеру A
определяют блок
@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h
добавить обработчик блока (слушатель) , где вам нужно значение (например, вам нужен ваш ответ API в ControllerA или вам нужны данные ContorllerB на A)
// in ContollerA.m
- (void)viewDidLoad {
[super viewDidLoad];
__unsafe_unretained typeof(self) weakSelf = self;
self.selectedVoucherBlock = ^(NSString *voucher) {
weakSelf->someLabel.text = voucher;
};
}
Перейти к контроллеру B
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
[self.navigationController pushViewController:vc animated:NO];
пожарный блок
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
NSString *voucher = vouchersArray[indexPath.row];
if (sourceVC.selectVoucherBlock) {
sourceVC.selectVoucherBlock(voucher);
}
[self.navigationController popToViewController:sourceVC 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
Таким образом, мы можем передавать данные из одного контроллера представления в другой контроллер представления ...
Я видел много людей, которые усложняли это, используя метод 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 строки кода внутри метода, и все готово.
Существует 3 типа для передачи данных из одного ViewController в другой ViewController.
Ссылка на демонстрационный проект здесь - https: / /github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers
Ссылка на демонстрационный проект здесь - https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers
Это действительно отличный учебник для всех, кто этого хочет. Вот пример кода:
- (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];
}
}
Я рекомендую блоки / замыкания и специальные конструкторы.
Предположим, вам нужно передать строку из FirstViewController в SecondViewController.
Ваш первый контроллер просмотра.
class FirstViewController : UIViewController {
func moveToViewControllerB() {
let second_screen = SecondViewController.screen(string: "DATA TO PASS", call_back: {
[weak self] (updated_data) in
///This closure will be called by second view controller when it updates something
})
self.navigationController?.pushViewController(second_screen, animated: true)
}
}
Ваш второй контроллер просмотра
class SecondViewController : UIViewController {
var incoming_string : String?
var call_back : ((String) -> Void)?
class func screen(string: String?, call_back : ((String) -> Void)?) -> SecondViewController {
let me = SecondViewController(nibName: String(describing: self), bundle: Bundle.main);
me.incoming_string = string
me.call_back = call_back
return me
}
// Suppose its called when you have to update FirstViewController with new data.
func updatedSomething() {
//Executing block that is implemented/assigned by the FirstViewController.
self.call_back?("UPDATED DATA")
}
}
Я предпочитаю делать это без делегатов и сегментов. Это можно сделать с помощью пользовательского init или установив дополнительные значения.
1. Custom init
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
print(success)
})
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
private let completionClosure: ((Bool) -> Void)
init(string: String, completionClosure: ((Bool) -> Void)) {
self.completionClosure = completionClosure
super.init(nibName: nil, bundle: nil)
title = string
}
func finishWork() {
completionClosure()
}
}
2. Факультативные переменные
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB()
viewController.string = "Blabla"
viewController.completionClosure = { success in
print(success)
}
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
var string: String? {
didSet {
title = string
}
}
var completionClosure: ((Bool) -> Void)?
func finishWork() {
completionClosure?()
}
}
Используйте центр уведомлений для передачи данных из одного вида в другой. Шаблон слушателя-наблюдателя работает лучше всего. Другим обходным путем может быть создание одинаковых объектов в обоих классах. Создание объекта класса 2 в первом классе, доступ к объектам данных, которые необходимо передать, и их установка, а затем нажатие контроллера представления.
Создайте свойство на следующем view controller .h
и определите геттер и сеттер.
Добавить это 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];
Есть множество способов сделать это, и важно выбрать правильный. Вероятно, одно из самых важных архитектурных решений заключается в том, каким образом код модели будет доступен или доступен во всем приложении.
Некоторое время назад я написал сообщение в блоге об этом: Совместное использование кода модели . Вот краткое резюме:
Один из подходов состоит в том, чтобы делиться указателями на объекты модели между контроллерами представления.
Поскольку подготовка к переходу является наиболее распространенным, приведем пример:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var next = segue.destinationViewController as NextViewController
next.dataSource = dataSource
}
Другой подход заключается в обработке экрана, заполненного данными одновременно, и вместо того, чтобы связывать контроллеры представления друг с другом, соединяйте каждый контроллер представления с одним источником данных, к которому они могут обращаться независимо.
Наиболее распространенный способ, которым я видел это, - это одноэлементный экземпляр. Поэтому, если ваш одноэлементный объект был DataAccess
, вы могли бы сделать следующее в методе viewDidLoad UIViewController:
func viewDidLoad() {
super.viewDidLoad()
var data = dataAccess.requestData()
}
Существуют инструменты добавления, которые также помогают передавать данные:
Приятно, что в Core Data есть обратные отношения. Поэтому, если вы хотите просто дать NotesViewController объект notes, вы можете это сделать, потому что он будет иметь обратную связь с чем-то другим, таким как блокнот. Если вам нужны данные на ноутбуке в NotesViewController, вы можете вернуться к графу объектов, выполнив следующие действия:
let notebookName = note.notebook.name
Подробнее об этом читайте в моем блоге: Совместное использование кода модели [1 125]
Передача данных из ViewController 2 (назначение) в viewController 1 (Source) является более интересной вещью. Предполагая, что вы используете storyBoard, это все способы, которые я узнал:
Это уже обсуждалось здесь.
Я обнаружил, что есть еще несколько способов:
- Использование обратных вызовов блока:
использовать его в методе 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 кнопка «возврат» к зеленой кнопке выхода (размотка) видеомагнитофона. Теперь у вас есть переход, который «возвращается», поэтому вы можете использовать свойство destinationViewController в prepareForSegue в VC2 и изменить любое свойство VC1, прежде чем оно вернется.
Еще один вариант использования раскадровок Undwind (Выход) - вы можете использовать метод, который вы написали в VC1
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
NextViewController *nextViewController = segue.sourceViewController;
self.unwindLabel.text = nextViewController.unwindPropertyPass;
}
И в prepareForSegue из VC1 вы можете изменить любое свойство, которое вы хотите поделиться.
В обоих вариантах раскрутки вы можете установить свойство тега кнопки и проверить его в prepareForSegue.
Надеюсь, я что-то добавил к обсуждению.
:) Приветствия.
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;
Если вы хотите отправить данные из одного в другой 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 без установки какого-либо делегата. ;)
В моем случае я использовал одноэлементный класс, который может работать как глобальный объект, предоставляя доступ к данным практически из любого места в приложении. Первое, что нужно сделать - создать класс синглтона. Пожалуйста, обратитесь к странице: « Как должен выглядеть мой синглтон Objective C? » И что я сделал, чтобы сделать объект глобально доступным, просто импортировал его в appName_Prefix.pch
, который предназначен для применения оператора import в каждом классы. Чтобы получить доступ к этому объекту и использовать его, я просто реализовал метод класса для возврата общего экземпляра, который содержит свои собственные переменные
Передача данных между 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 ];
В настоящее время я участвую в решении этой проблемы с открытым исходным кодом через проект 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 и передать данные, вы создаете новое намерение и добавляете данные в его словарь (saveInstanceState). Затем просто установите текущее намерение фабрики:
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];
}
Надеюсь, некоторые из вас найдут это решение полезным / интересным.
Я знаю, что это непростая тема, но для тех, кто хочет ответить на этот вопрос с уклоном SWIFT и хочет получить простой пример, здесь мой метод перехода для передачи данных, если вы используете переход, чтобы обойти.
Это похоже на выше, но без кнопок, меток и тому подобного. Просто передавая данные из одного представления в другое.
Настройка раскадровки
Есть три части.
Это очень простой макет представления с переходом между ними.
Вот настройки для отправителя
Вот настройка для приемника.
Наконец, установка для перехода.
Контроллеры представления
Мы сохраняем это простым, поэтому никаких кнопок а не действия, мы просто перемещаем данные от отправителя к получателю при загрузке приложения и затем выводим переданное значение на консоль.
Эта страница принимает изначально загруженное значение и передает его.
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
}
}
Эта страница просто отправляет значение переменной в консоль при загрузке. К этому моменту наш любимый фильм должен находиться в этой переменной.
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)")
}
}
Вот как вы можете справиться с этим, если хотите использовать переход, и у вас нет страниц под контроллером навигации.
После запуска он должен автоматически переключиться на представление получателя и передать значение от отправителя получателю, отображая это значение в консоли.
Это не способ сделать это, вы должны использовать делегатов, я предполагаю, что у нас есть два контроллера представления ViewController1 и ViewController2, и этот элемент проверки находится в первом, и когда его состояние изменяется, вы хотите что-то сделать в ViewController2, чтобы добиться этого надлежащим образом, вы должны сделать следующее:
Добавить новый файл в ваш проект (Протокол Objective-C) Файл -> Новый, теперь назовите его 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];
Теперь все готово, когда вы обнаруживаете событие проверки, измененное в V iewController1, все, что вам нужно сделать, это ниже
[delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control
Пожалуйста, скажите мне, если есть что-то, что не ясно, если я не правильно понял ваш вопрос.
ну, у нас есть несколько способов, с помощью которых мы можем работать с системой делегатов или использовать storyboardSegue
1- As working with setter and getter method like in viewController.h
@property (retain, nonatomic) NSString *str;
now, in viewController.m
@synthesize str;
here i have pdf url and segue to another viewController like this and pdfObject is my pdfModel basicilly is NSOBJECT class.
str =[NSString stringWithFormat:@"%@",pdfObject.objPath];
NSLog(@"pdfUrl :***: %@ :***:",pdfUrl);
[self performSegueWithIdentifier:@"programPDFViewController_segue" sender:self];
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"programPDFViewController_segue"]){
programPDFViewController *pdfVC = [segue destinationViewController];
[pdfVC setRecievedPdfUrl:str];
}
}
Теперь успешно я получил строку URL-адреса в формате PDF и другой ViewController и использовать эту строку в веб-просмотре ...
2- При работе с такими делегатами у меня есть один класс утилит NSObject, содержащий мои методы dateFormatter, sharedInstance, EscapeWhiteSpaceCharacters, convertImageToGrayScale и другие методы, с которыми я работал на протяжении всего процесса. application, теперь в utilities.h
. В этом случае вам не нужно создавать переменные при постоянном анализе данных от одного к другому контроллеру представления один раз, когда ваша созданная строковая переменная в utilities.h просто делает его равным nil; и снова использовался
@interface Utilities : NSObject
Utilities.h
+(Utilities*)sharedInstance;
@property(nonatomic,retain)NSString* strUrl;
, теперь в утилитах.m
@implementation utilities
+(utilities*)sharedInstance
{
static utilities* sharedObj = nil;
if (sharedObj == nil) {
sharedObj = [[utilities alloc] init];
}
return sharedObj;
}
now its done come to your firstViewController.m and call delegate
NSString*str =[NSString stringWithFormat:@"%@",pdfObject.objPath];
[Connection sharedInstance].strUrl=nil;
[Connection sharedInstance].strUrl=str;
Now go to you secondViewController.m directly use it without creating variable
in viewwillapear what i did
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[self webViewMethod:[Connection sharedInstance].strUrl];
}
-(void)WebViewMethod:(NSString)Url{
// working with webview enjoy coding :D
}
эта работа делегата надежна с управлением памятью
После дополнительных исследований выяснилось, что протоколы и делегаты - правильный путь / Apple предпочитает делать это.
В конечном итоге я использовал этот пример
Обмен данными между контроллерами представления и другими объектами @ iPhone Dev SDK
Работал нормально и позволил мне передать строку и массив вперед и назад между моими взглядами.
Спасибо за вашу помощь.
M в MVC предназначен для «Модели», а в парадигме MVC роль классов моделей заключается в управлении данными программы. Модель является противоположностью представления - представление знает, как отображать данные, но ничего не знает о том, что делать с данными, тогда как модель знает все о том, как работать с данными, но ничего о том, как их отображать. Модели могут быть сложными, но это не обязательно - модель для вашего приложения может быть такой же простой, как массив строк или словарей.
Роль диспетчера заключается в посредничестве между представлением и моделью. Следовательно, им нужна ссылка на один или несколько объектов вида и один или несколько объектов модели. Допустим, ваша модель представляет собой массив словарей, каждый из которых представляет одну строку в вашей таблице. Корневое представление для вашего приложения отображает эту таблицу, и оно может отвечать за загрузку массива из файла. Когда пользователь решает добавить новую строку в таблицу, он нажимает какую-то кнопку, и ваш контроллер создает новый (изменяемый) словарь и добавляет его в массив. Чтобы заполнить строку, контроллер создает контроллер подробного представления и дает ему новый словарь. Контроллер подробного представления заполняет словарь и возвращает. Словарь уже является частью модели, поэтому больше ничего не должно происходить.
Если вы хотите передать данные с одного контроллера на другой, попробуйте этот код
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];
}
Поскольку SwiftUI
Думает о @EnvironmentObject как о более умном, более простом способе использовать @ObservedObject на большом количестве представлений. Вместо того, чтобы создавать некоторые данные в поле зрения A, затем передавая его представлению B, затем представлению C, затем представлению D прежде наконец использовать его, можно создать его в поле зрения и поместить его в среду так, чтобы представления B, C, и D автоматически имели доступ к нему.
Примечание: объекты Среды должны быть предоставлены представлением †предка “, если SwiftUI can’t находит, что объект среды корректного типа you’ll получает катастрофический отказ. Это запрашивает предварительные просмотры также, так быть осторожным.
Как пример, here’s заметный объект, который хранит пользовательские настройки:
class UserSettings: ObservableObject {
@Published var score = 0
}