在objective-C中设置/获取全局变量

时间:2012-11-04 17:08:03

标签: objective-c global-variables

我正在编写一个应用程序,它是一种字典 - 它向用户显示一个术语列表,当单击时,会弹出一个包含该定义的对话框。定义本身也可能包含术语,反过来用户可以单击以启动另一个定义弹出窗口。

我的主应用程序存储在'myViewController.m'中。它调用一个自定义的UIView类,'CustomUIView.m'来显示定义(这是弹出的对话框)。一切正常。

然后,CustomUIView的文本链接应该能够启动更多定义。在我的CustomUIView中点击文本时,它会启动另一个CustomUIView。问题是,这个新的CustomUIView无法访问包含我所有字典的术语和定义的哈希映射;这只适用于我的主应用程序'myViewController.m'。

不知何故,我需要制作我的哈希映射 dictionaryHashMap ,对 CustomUIView 类的每个实例都是可见的。当应用程序打开时, dictionaryHashMap myViewController.m 中创建,此后不再更改。

我不希望限制可以同时打开的CustomUIViews的数量(我有理由这样做!),因此发送的副本会有点资源消耗。 dictionaryHashMap 到CustomUIView的每个实例。据推测,解决方案是使 dictionaryHashMap 成为一个全局变量。

我的一些代码:

来自myViewController.m:

- (void)viewDidLoad
{
    self.dictionaryHashMap = [[NSMutableDictionary alloc] init]; // initialise the dictionary hash map
    //... {Code to populate dictionaryHashMap}
}

// Method to pop up a definition dialog
- (void)displayDefinition:(NSString *) term
{
    NSArray* definition = [self.dictionaryHashMap objectForKey:term]; // get the definition that corresponds to the term
    CustomUIView* definitionPopup = [[[CustomUIView alloc] init] autorelease]; // initialise a custom popup
    [definitionPopup setTitle: term];
    [definitionPopup setMessage: definition];
    [definitionPopup show];
}

// Delegation for sending URL presses in CustomUIView to popupDefinition
#pragma mark - CustomUIViewDelegate
+ (void)termTextClickedOn:(CustomUIView *)customView didSelectTerm:(NSString *)term
{
        myViewController *t = [[myViewController alloc] init]; // TODO: This instance has no idea what the NSDictionary is
        [t displayDefinition:term];
}

来自CustomUIView.m:

// Intercept clicks on links in UIWebView object
- (BOOL)webView: (UIWebView*)webView shouldStartLoadWithRequest: (NSURLRequest*)request navigationType: (UIWebViewNavigationType)navigationType {
    if ( navigationType == UIWebViewNavigationTypeLinkClicked ) {
        [myViewController termTextClickedOn:self didSelectTerm:request];
        return NO;
    } 
    return YES;
}

非常感谢有关如何使 dictionaryHashMap CustomUIView 可见的任何提示。

我尝试通过执行以下操作来创建 dictionaryHashMap 全局:

  • 将'self.dictionaryHashMap'的所有实例更改为'dictionaryHashMap'
  • 添加行'extern NSMutableDictionary * dictionaryHashMap;'到 CustomUIView.h
  • myViewController.m 中添加以下实现内容:'NSMutableDictionary * dictionaryHashMap = nil;'

但是,DictionaryHashMap仍然对CustomUIView不可见。据我所知,它实际上仍然是 myViewController 的本地变量......

3 个答案:

答案 0 :(得分:3)

将引用(指针)传递给dictionaryHashMap并不占用大量资源。指向对象的指针只有4个字节。您可以将它从视图控制器传递到视图。

但我不知道为什么你甚至需要那样做。您的视图在单击术语时向视图控制器发送消息(termTextClickedOn:didSelectTerm:)。并且视图控制器已经具有对字典的引用,因此它可以处理查找。为什么视图还需要对字典的引用?

无论如何,如果您想使字典成为全局字典,那么在application:didFinishLaunchingWithOptions:中的应用委托中初始化字典会更合适。你甚至可以将字典作为你的app委托的属性并懒惰地初始化它。

更新

在您评论termTextClickedOn:didSelectTerm:是一种类方法之前,我没有注意到。我假设它是一个实例方法,因为myViewController以小写字母开头,而iOS编程中的约定是类以大写字母开头。 (当您遵循约定时,您可以更轻松地获得良好的帮助!)

这是我推荐的内容。首先,将myViewController重命名为MyViewController(或更好,DefinitionViewController)。

给它一个引用字典的属性。无论代码创建什么MyViewController的新实例都负责设置此属性。

为目标和操作提供CustomUIView属性:

@property (nonatomic, weak) id target;
@property (nonatomic) SEL action;

创建视图时设置这些属性:

- (void)displayDefinition:(NSString *)term {
    NSArray* definition = [self.dictionaryHashMap objectForKey:term];
    CustomUIView* definitionPopup = [[[CustomUIView alloc] init] autorelease]; // initialise a custom popup
    definitionPopup.target = self;
    definitionPopup.action = @selector(termWasClicked:);
    ...

在视图的webView:shouldStartLoadWithRequest:方法中,从网址请求中提取字词并将其发送到目标/操作:

- (BOOL)webView: (UIWebView*)webView shouldStartLoadWithRequest: (NSURLRequest*)request navigationType: (UIWebViewNavigationType)navigationType {
    if ( navigationType == UIWebViewNavigationTypeLinkClicked ) {
        NSString *term = termForURLRequest(request);
        [self.target performSelector:self.action withObject:term];
        return NO;
    } 
    return YES;
}

在视图控制器的termWasClicked:方法中,创建新的视图控制器并设置其字典属性:

- (void)termWasClicked:(NSString *)term {
    MyViewController *t = [[MyViewController alloc] init];
    t.dictionary = self.dictionary;
    [t displayDefinition:term];
}

答案 1 :(得分:0)

创建一个将用作单例的类。 Example

答案 2 :(得分:0)

您应始终将数据保存在mvc模式建议的单独类中,并且可以通过对所有字典术语使用单例类并在需要时从每个自定义视图访问它们来实现。