AppDelegate 被不同的类访问,来自 RootController.m

Posted

技术标签:

【中文标题】AppDelegate 被不同的类访问,来自 RootController.m【英文标题】:AppDelegate Being accessed from different classes, from RootController.m 【发布时间】:2009-11-24 13:41:47 【问题描述】:

我的问题是从控制器(恰好是我的 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】:

我看不到您使用来自应用委托的“selectedMaker”的数据填充DetailsViewController 中的selectedMaker 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]; 

编辑01:

所以...在 TechZen 的建议下,我 试图将我的 NSDictionary 移出 我的 RootViewController。

(1) 我不确定您为什么拥有应该完成的 SelectedMaker 类。您似乎将课程与NSMutableDictionary 混淆了。该类没有任何明显的理由返回包含它自己的 iVar 值的字典。这是完全多余的。您似乎已经有一个名为ViolinMaker 的类,它封装了每个小提琴制作者记录的所有数据。

(2) SelectedMaker 的初始化方法没有正确实现。看起来你必须在调用-[SelectedMaker init] 之前调用-[SelectedMaker initWithsName:..],否则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'. TheviolinMaker`object 包含您需要的所有数据。

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

编辑02:

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

您只需将字典定义为应用程序委托中的实例变量一次。因此,您将拥有一个可变字典,其中每个值都是ViolinMaker,每个键都是小提琴制造商的某些属性,例如名称。让我们称之为violinMakersDict。然后,在您的应用程序中的任何位置,您都可以通过首先调用应用程序委托和访问violinMakersDict 来访问字典。

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

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

【讨论】:

非常酷,这正是我所要求的,因为我确实觉得我正在实例化一个新变量,并且它只是具有相同的名称......但是我如何将值加载到appDelegate??抱歉,我只是不知道如何将这些值加载到 Appdelegate 中?非常感谢!柯克 对不起,不习惯这个网站,非常感谢TechZen的帮助。我的问题是我从 RootViewController(一个 UITableViewController,在 tableView didSelectRowAtIndexPath 内)加载 NSMuteableDictionary,而不是在 appDelegate 内。我可以在那里加载信息,我只是不知道如何从那里进入另一个视图。我明白你在说什么,但它只是说黄色警告“UIApplication 可能无法响应 -selected Maker” 如果数据在 rootViewController 中,您需要先将数组分配给子控制器,然后再将其推送到导航堆栈。 (如果您需要,我可以稍后提供一个示例。)作为一项规则,您不会将数据保存在视图控制器中。应该有单独的对象来保存数据。如果多个控制器必须访问数据,则尤其如此。应用程序委托通常是停放它的最佳位置。阅读模型-视图-控制器设计模式。了解所有基于 Objective-C 的 API 的工作原理非常重要。 我知道你的意思。我为我的 UITable 做了 4 个自定义单元格。但是,如果我要像这里一样创建字典,roseindia.net/tutorial/iphone/examples/nslog/… 我无法访问在对象的 RootViewController.m 表访问函数中调用的 didSelectRow 函数。我必须在 NSDictionary 代码所在的位置执行此操作。 IE [violinMaker name] 我只需要访问在 RootViewcontroller.h/m 文件中创建的 NSMutableDictionary。这也意味着我也无法获得在 appdelegate 中创建的值。你看到我的问题还是我没有看到答案? 您需要将数据保存在应用程序委托中,而不是任何控制器中。您可以从应用程序中的任何位置调用代理。理想情况下,您将有一个自定义对象来处理您的数据,并且只需在应用程序委托中对其进行引用。如果您的数据只是一个简单的数组,您通常不会打扰,但是随着您的模型变得越来越复杂,您需要一个自定义类来管理它。..

以上是关于AppDelegate 被不同的类访问,来自 RootController.m的主要内容,如果未能解决你的问题,请参考以下文章

导入 AppDelegate

来自 AppDelegate 的 Objective-c 导入功能不起作用

Java静态元素被不同的类访问

来自 AppDelegate 的 UISegmentedControl

Android - Ipay88 出现错误访问被拒绝找到属性“ro.serialno”

来自 AppDelegate 的当前 viewController 崩溃/空屏