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

发布于 2024-08-12 03:18:54 字数 4883 浏览 8 评论 0原文

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

我希望这可以帮助其他人弄清楚这一点,因为这确实花了我很多时间,我希望你能从我学到的东西中得到一些东西。

真挚地, 柯克

My problem is in getting the information from a controller(which happens to be my rootViewController) to another view. In trying to get access to it through the app delegate, I was not able to get it working. I have found how to do this, but this inturn created another problem of getting the view inside a modal view controller to actually display the data. Below I have posted both the appDelegate information, and an NSMutable Dictionary solution code for those that may need help too.

I had tried for more than a week to solve ths problem on my own. My issue ended up being how to access the appDelegate, which was why I was having a problem with the NSDictionary. So in the end the issue wasn't the NSDictionary, although had I gone further it would have been a problem I am sure.

Firstly I would like to thank TechZen for helping me to see I was over programming, and point me in the right direction.

Here is what I learned.

Assign your variable in the 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] ;
}

In the ViewController.m assign the variable to the appDelegate. I did this inside a tableView function 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];

Now in your view Controller you want to load the variable from the appDelegate, set it up like this.

#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

and in the viewController.m file;

#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

..... and assign it to what ever you want now!

I hope this helps everyone. You could at this point drop the NSArray from there into a NSDictionary, but the access is now with keys and values, so a bit more complicated at this point to access, but of course advantages. I just cannot get that totally down yet, and have backed away from that method to just use a NSArray for now.

Below is a sample of a Makers h and m file for you to see as well.

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

and its Maker.m file;

#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

I hope this helps others get this straight, as it really cost me a lot of time and I hope you can get a bit from what I learned.

Sincerely,
Kirk

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

潜移默化 2024-08-19 03:18:54

我没有看到您使用应用程序委托的“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]; 
}

Edit01:

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

(1) 我不确定为什么你有它应该完成的 SelectedMaker 类。您似乎将该类与 NSMutableDictionary 混淆了。该类没有任何明显的理由返回包含其自己的 iVar 值的字典。这完全是多余的。您似乎已经有一个名为 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' 中的数据的任何视图中使用这三行。 violinMaker`对象包含您需要的所有数据。

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

编辑02:

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

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

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

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

I don't see any point where you populate the selectedMaker ivar in the DetailsViewController with data from the app delegate's `selectedMaker'. Just because they have the same name doesn't mean they share the same data.

You need to assign or copy the values from the app delegate to the view controller. The quick and dirty way is to do something like:

@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:

So... at the suggestion of TechZen i
have tried to move my NSDictionary out
of my RootViewController.

(1) I'm not sure why you have the SelectedMaker class of what it is supposed to accomplish. You seem to have confused the class with a NSMutableDictionary. The class doesn't have any apparent reason to return a dictionary containing the values of it's own iVars. This is completely redundant. You already appear to have a class called ViolinMaker that encapsulates all the data for each violin maker record.

(2) The initializations methods for SelectedMaker are not implemented correctly. It looks like you have to call -[SelectedMaker initWithsName:..] before you call -[SelectedMaker init] otherwise init has no clue what the keys are.

(3) In any case, in the didSelectRow method, you don't actually initialize an instance of SelectedMaker. This line:

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

Does not create an instance of SelectedMaker but rather a NSMutableDictionary and more or less cast it to the SelectedMaker class. This is why you get the compiler warning from the for-loop.

(4) I don't see any need for the SelectedMaker class at all. These lines:

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

Appear to provide you all the information you need to populate any particular row in your table or your detail view. You can use these three line in any view in which you need to access the data in appDelegate.violinMakers'. TheviolinMaker`object contains all the data you need.

I think you are making this more complicated than it has to be. All you need is (A) a class that encapsulates the data for each record fetched from your SQL. In this case it looks like ViolinMaker does this. (B) You need an array (or other collection) in the app delegate to store the multiple ViolinMaker instances. (C) You need code in each viewcontroller that will access the array/collection in the app delegate so that the viewcontroller can select the ViolinMaker instances it needs.

Edit02:

no I cannot use those 3 lines, as the
'objectAtIndex:indexPath.row' is only
available inside the didSelectRow
function. Which means I would have to
reconstruct the table and all of its
data.

You just define the dictionary once as an instance variable in your app delegate. So, you would have a mutable dictionary where each value was ViolinMaker and each key was some attribute of a violin maker such as the name. Let's call that violinMakersDict.Then, anywhere in your app, you would access the dictionary by first calling the app delegate and the accessing the violinMakersDict.

To populate a table, you would need to extract the some values as an array. Most likely, you would takes the keys which are names of violin makers. Then you would sort the array alphabetically, then you would populate each row with the value in the array at the index.row value.

Likewise, if you need to add data in one view, you can write to the violinMakersDict and then access that data from another view by again calling the app delegate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文