AppDelegate从RootController.m从不同的类访问

时间:2009-11-24 13:41:47

标签: cocoa variables nsdictionary didselectrowatindexpath retained-in-memory

我的问题是从控制器(恰好是我的rootViewController)获取信息到另一个视图。在尝试通过应用程序委托访问它时,我无法使其正常工作。我已经找到了如何做到这一点,但是这个内容创建了另一个问题,即在模态视图控制器中获取视图以实际显示数据。下面我发布了appDelegate信息和NSMutable Dictionary解决方案代码,供那些可能需要帮助的人使用。

我已经尝试了一个多星期来自己解决这个问题。我的问题最终是如何访问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。

以下是Makers h和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

我希望这有助于其他人直截了当,因为它花了我很多时间,我希望你能从我所学到的东西中得到一点。

此致 柯克

1 个答案:

答案 0 :(得分:2)

我没有看到您使用app delegate的“selectedMaker”中的数据填充selectedMaker中的DetailsViewController ivar的任何一点。仅仅因为它们具有相同的名称并不意味着它们共享相同的数据。

您需要将应用程序委托中的值分配或复制到视图控制器。快速而肮脏的方式是做类似的事情:

@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-loop获得编译器警告的原因。

(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`object包含您需要的所有数据。

我认为你让它变得比以前更加复杂。您只需要(A)一个类,它封装从SQL获取的每个记录的数据。在这种情况下,看起来像ViolinMaker这样做。 (B)您需要在app委托中使用数组(或其他集合)来存储多个ViolinMaker实例。 (C)您需要在每个viewcontroller中使用代码来访问app委托中的数组/集合,以便viewcontroller可以选择所需的ViolinMaker实例。

Edit02:

  

不,我不能用那3行作为   'objectAtIndex:indexPath.row'只是   在didSelectRow中可用   功能。这意味着我必须这样做   重建表及其所有表   数据

您只需将字典定义为应用委托中的实例变量一次。所以,你会有一个可变字典,每个值都是ViolinMaker,每个键都是小提琴制作者的一些属性,比如名字。我们称之为violinMakersDict。然后,在应用程序的任何地方,您都可以通过首先调用应用程序委托和访问violinMakersDict来访问字典。

要填充表格,您需要将某些值作为数组提取。最有可能的是,你会拿出小提琴制造商的名字。然后,您将按字母顺序对数组进行排序,然后使用index.row值中的数组中的值填充每一行。

同样,如果您需要在一个视图中添加数据,您可以写入violinMakersDict,然后再次调用app delegate从另一个视图访问该数据。