1

Моя проблема заключается в получении информации от контроллера (который, случается, с моим rootViewController) к другому представлению. Пытаясь получить доступ к нему через делегат приложения, я не смог заставить его работать. Я нашел, как это сделать, но этот inturn создал еще одну проблему: получить представление внутри модального контроллера представления для фактического отображения данных. Ниже я опубликовал как информацию appDelegate, так и код решения NSMutable Dictionary для тех, кому может понадобиться помощь.AppDelegate Доступен из разных классов, от RootController.m

Я пробовал больше недели, чтобы решить эту проблему самостоятельно. Моя проблема закончилась тем, что я получил доступ к appDelegate, поэтому у меня возникла проблема с NSDictionary. Поэтому в конце концов вопрос был не NSDictionary, хотя, если бы я пошел дальше, это было бы проблемой, я уверен.

Во-первых, я хотел бы поблагодарить TechZen за то, что он помог мне увидеть, что я над программированием, и назовите меня в правильном направлении.

Вот что я узнал.

Назначьте свою переменную в appDelegate.

AppDelegate.h

@interface AppDelegate : NSObject < UIApplicationDelegate, UINavigationControllerDelegate > 
{ 
    UIWindow *window; 
    UINavigationController *navController; 

    // Array to store the Makers Objects 
    NSMutableArray *makers; 

} 

@property (nonatomic, retain) IBOutlet UIWindow *window; 
@property (nonatomic, retain) IBOutlet UINavigationController *navController; 

@property (retain, nonatomic) NSMutableArray *makers; 
@end 

AppDelegate.m

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{ 

    makers = [[NSMutableArray alloc] init] ; 
} 

В ViewController.m назначить переменную в AppDelegate. Я сделал это внутри функции tableView didSelectRowAtIndexPath.

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

// The line below loads it into the variable, the one above takes it and makes it available for other view Controllers. 

     Maker *maker = (Maker *)[appDelegate.makers objectAtIndex:indexPath.row]; 

// the combination of the above and below also loads the information into another array in this view controller, defined in an NSObject Controller called Maker (.h and .m files) 

     maker = [self.Makers objectAtIndex:indexPath.row]; 

Теперь на ваш взгляд контроллера вы хотите загрузить переменную из AppDelegate, установите его, как это.

#import <UIKit/UIKit.h> 

#import "AppDelegate.h" 
#import "Maker.h" 

@class AppDelegate; 

@interface DetailsViewController : UIViewController 
{ 

     AppDelegate *dappDelegate; 
    DetailsViewController *detailsView; 

    IBOutlet UITextView *makerDescription; 

} 

@property (retain, nonatomic) AppDelegate *dappDelegate; 

@property (nonatomic, retain) DetailsViewController *detailsView; 

@property (nonatomic, retain) IBOutlet UITextView *makerDescription; 

@end 

и в файле viewController.m;

#import "DetailsViewController.h" 
#import "AppDelegate.h" 

@synthesize dappDelegate; 

- (void)viewWillAppear:(BOOL)animated // or ViewDidLoad not sure which is better. 

    dappDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; 
    NSString *newLocalVariable = [dappDelegate.makers description]; 

NSLog(@"newLocalVariable: %@", [dappDelegate.makers description]); 
// This is for verifying you have it loaded. 'description' is defined in the Maker NSObject, see below for those files, and above for where it was assigned originally 

..... и назначьте его тем, что вы хотите сейчас!

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

Ниже приведен образец файлов производителей и файлов m, которые вы также можете увидеть.

Maker.h 

@interface Maker : NSObject 
{ 
    NSString *name; 
    NSString *address; 
    NSString *city; 
    NSString *postalcode; 
    NSString *country; 
    NSString *phonenumber; 
    NSString *email; 
    NSString *description; 
    NSString *services; 
    NSString *website; 
} 

@property (nonatomic, copy) NSString *name; 
@property (nonatomic, copy) NSString *address; 
@property (nonatomic, copy) NSString *city; 
@property (nonatomic, copy) NSString *postalcode; 
@property (nonatomic, copy) NSString *country; 
@property (nonatomic, copy) NSString *phonenumber; 
@property (nonatomic, copy) NSString *email; 
@property (nonatomic, copy) NSString *description; 
@property (nonatomic, copy) NSString *services; 
@property (nonatomic, copy) NSString *website; 

- (id)initWithName:(NSString *)n address:(NSString *)a city:(NSString *)c postalcode:(NSString *)z country:(NSString *)o phonenumber:(NSString *)p email:(NSString *)e description:(NSString *)d services:(NSString *)s website:(NSString *)w; 

@end 

и его файл Maker.m;

#import "ViolinMaker.h" 

@implementation Maker 
@synthesize name, address, city, postalcode, country, phonenumber, email, description, services, website; 

- (id)initWithName:(NSString *)n address:(NSString *)a city:(NSString *)c postalcode:(NSString *)z country:(NSString *)o phonenumber:(NSString *)p email:(NSString *)e description:(NSString *)d services:(NSString *)s website:(NSString *)w; 
{ 
    self.name = n; 
    self.address = a; 
    self.city = c; 
    self.postalcode = z; 
    self.country = o; 
    self.phonenumber = p; 
    self.email = e; 
    self.description = d; 
    self.services = s; 
    self.website = w; 
    return self; 
} 
@end 

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

С уважением, Кирк

+0

В чем вопрос? Вы отредактировали его? –

ответ

2

Я не вижу смысла, где вы заселить selectedMaker Ивар в DetailsViewController с данными из приложения делегата `selectedMaker». Просто потому, что они имеют одно и то же имя, это не значит, что они используют одни и те же данные.

Вам необходимо назначить или скопировать значения из делегата приложения в контроллер вида. Быстрый и грязный способ сделать что-то вроде:

@implementation DetailsViewController 

... 

-(void) viewDidLoad{ 
//selectedMaker=[[UIApplication sharedApplication] selectedMaker]; <-- this is wrong 
//Edit, this is the correct call to app delegate 
selectedMaker=[[[UIApplication sharedApplication] delegate] selectedMaker]; 
} 

Edit01:

Так ... по предложению TechZen я попытался пошевелить NSDictionary из моего RootViewController.

(1) Я не уверен, почему у вас есть класс SelectedMaker того, что он должен выполнить. Кажется, вы путаете класс с NSMutableDictionary. У класса нет никаких очевидных причин для возврата словаря, содержащего значения его собственных iVars. Это полностью избыточно. У вас уже появился класс с именем ViolinMaker, который инкапсулирует все данные для каждой записи создателя скрипки.

(2) Методы инициализации для SelectedMaker выполнены неправильно. Похоже, вы должны позвонить -[SelectedMaker initWithsName:..], прежде чем позвонить -[SelectedMaker init], иначе init не имеет понятия, что такое ключи.

(3) В любом случае в методе didSelectRow вы фактически не инициализируете экземпляр SelectedMaker. Эта линия:

SelectedMaker *selectedMaker = [[[NSMutableDictionary alloc]retain] initWithObjects: objects forKeys: keys]; 

Не создает экземпляр SelectedMaker, а скорее NSMutableDictionary и более или менее брось в SelectedMaker класса. Вот почему вы получаете предупреждение компилятора из цикла for.

(4) Я не вижу необходимости в классе SelectedMaker вообще. Эти строки:

ViolinMakerAppDelegate *appDelegate = (ViolinMakerAppDelegate *)[[UIApplication sharedApplication] delegate]; 
ViolinMaker *violinMaker = (ViolinMaker *)[appDelegate.violinMakers objectAtIndex:indexPath.row]; 
violinMaker = [self.filteredViolinMakers objectAtIndex:indexPath.row]; 

появляющиеся, чтобы предоставить вам всю информацию, которую нужно заполнить какую-либо конкретную строку в таблице или вашей точки зрения детализации. Вы можете использовать эти три строки в любом представлении, в котором вам нужно получить доступ к данным в файле appDelegate.violinMakers'. The. Функция violinMaker содержит все необходимые данные.

Я думаю, что вы делаете это более сложным, чем это должно быть. Все, что вам нужно - это (A) класс, который инкапсулирует данные для каждой записи, извлеченной из вашего SQL. В этом случае похоже, что ViolinMaker делает это. (B) Вам нужен массив (или другая коллекция) в делегате приложения для хранения нескольких экземпляров ViolinMaker. (C) Вам нужен код в каждом диспетчере представлений, который будет обращаться к массиву/коллекции в делегате приложения, чтобы viewcontroller мог выбрать экземпляры ViolinMaker, в которых он нуждается.

Edit02:

нет, я не могу использовать эти 3 строки, как 'objectAtIndex: indexPath.row' не только доступны внутри функции didSelectRow . Это означает, что мне пришлось бы восстановить таблицу и все ее данные .

Вы просто определяете словарь один раз как переменную экземпляра в своем делете приложения. Таким образом, у вас будет изменяемый словарь, где каждое значение равно ViolinMaker, и каждый ключ был атрибутом создателя скрипки, такого как имя. Назовем это violinMakersDict.Затем, в любом месте вашего приложения, вы получите доступ к словарю, сначала позвонив делегату приложения и доступу к скриптингу.

Чтобы заполнить таблицу, вам нужно извлечь некоторые значения в виде массива. Скорее всего, вы возьмете ключи, которые являются именами создателей скрипки. Затем вы сортируете массив по алфавиту, затем вы заполняете каждую строку значением в массиве по значению index.row.

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

+0

Очень круто, и это именно то, о чем я прошу, так как я чувствовал, что создаю новую переменную, и у нее просто одно и то же имя ... Но как мне загрузить значения в appDelegate ?? извините, я просто не понимаю, как загрузить эти значения в Appdelegate? Огромное спасибо! Kirk – Digiguy

+0

Извините, не используется для этого сайта, я очень ценю вашу помощь TechZen. Моя проблема заключается в том, что я загружаю NSMuteableDictionary из RootViewController (UITableViewController, внутри tableView didSelectRowAtIndexPath), а не внутри appDelegate. Я могу загрузить информацию там, я просто не понимаю, как это сделать в другом виде. Я вижу, что вы там говорите, но он просто говорит о желтом предупреждении. «UIApplication может не отвечать на« выбранный Maker » – Digiguy

+0

. Если данные находятся в корневом контроллере, вам нужно назначить массив субконтроллеру, прежде чем вы нажмете его на стек навигации. (Я могу привести пример позже, если вы его запросите.) Как правило, вы не храните данные в контроллере представления. Должен быть отдельный объект, содержащий данные. Это особенно верно, если более чем одному контроллеру приходится обращаться к данным. Делегат приложения обычно является лучшим местом для парковки. Ознакомьтесь с шаблоном проектирования Model-View-Controller. Это очень важно для понимания того, как работают все API на основе объектно-ориентированного интерфейса. – TechZen