Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c Obj-C:消失变量_Objective C_Variables_Memory Management_Uibutton_Nsdictionary - Fatal编程技术网

Objective c Obj-C:消失变量

Objective c Obj-C:消失变量,objective-c,variables,memory-management,uibutton,nsdictionary,Objective C,Variables,Memory Management,Uibutton,Nsdictionary,我对Objective-C还不熟悉,对于一个让我感到困惑的问题,我需要一些帮助。我称之为消失变量的问题。我将尝试在下面描述它 我正在尝试创建我自己的选项卡栏控制器和视图,因为我得出的结论是,UITabBarController和UITabBar不允许我做我需要做的事情(我需要彻底改变选项卡栏的外观) 我已经对UIViewController和UIView进行了子类化,分别创建了SYTabBarController和SYTabBar类 在SYTabBar中,我编写了一个方法,以编程方式将UIBut

我对Objective-C还不熟悉,对于一个让我感到困惑的问题,我需要一些帮助。我称之为消失变量的问题。我将尝试在下面描述它

我正在尝试创建我自己的选项卡栏控制器和视图,因为我得出的结论是,
UITabBarController
UITabBar
不允许我做我需要做的事情(我需要彻底改变选项卡栏的外观)

我已经对
UIViewController
UIView
进行了子类化,分别创建了
SYTabBarController
SYTabBar

SYTabBar
中,我编写了一个方法,以编程方式将
UIButton
s添加到我的视图中:

- (UIButton*) addButtonWithFrame:(CGRect)frame action:(SEL)action target:(id)target imageToken:(NSString*)imageToken
{
    UIButton *b = [[UIButton alloc]initWithFrame:frame];
    [b addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];

    UIImage
    *unselectedImage = [UIImage imageNamed:APPEND_STRING(@"TBI+Unselected+", @"imageToken")],
    *selectedImage   = [UIImage imageNamed:APPEND_STRING(@"TBI+Selected+", @"imageToken")],
    *selectedBgImage = [UIImage imageNamed:@"TBI+SelectedBG"];

    [b setImage:unselectedImage forState:UIControlStateNormal];
    [b setImage:selectedImage forState:UIControlStateHighlighted];
    [b setImage:selectedImage forState:UIControlStateSelected];
    [b setBackgroundImage:selectedBgImage forState:UIControlStateHighlighted];
    [b setBackgroundImage:selectedBgImage forState:UIControlStateSelected];
    [b setShowsTouchWhenHighlighted:NO];
    [b setAdjustsImageWhenHighlighted:NO];
    [b setAdjustsImageWhenDisabled:NO];
    [self addSubview:b];

    return b;
}
我在
SYTabBarController
中调用此方法来创建五个按钮:

    UIButton *button1 = [self.tabBar addButtonWithFrame:CGRectMake(0, 0, 64, 45)
                                                 action:@selector(changeView:)
                                                 target:self
                                             imageToken:@"Popular"];

    UIButton *button2 = [self.tabBar addButtonWithFrame:CGRectMake(64, 0, 64, 45)
                                                 action:@selector(changeView:)
                                                 target:self
                                             imageToken:@"Feed"];

    UIButton *button3 = [self.tabBar addButtonWithFrame:CGRectMake(64*2, 0, 64, 45)
                                                 action:@selector(changeView:)
                                                 target:self
                                             imageToken:@"Capture"];

    UIButton *button4 = [self.tabBar addButtonWithFrame:CGRectMake(64*3, 0, 64, 45)
                                                 action:@selector(changeView:)
                                                 target:self
                                             imageToken:@"Likes"];

    UIButton *button5 = [self.tabBar addButtonWithFrame:CGRectMake(64*4, 0, 64, 45)
                                                 action:@selector(changeView:)
                                                 target:self
                                             imageToken:@"Profile"];
然后,仍然在
SYTabBarController
中,我尝试将这五个按钮作为键添加到作为属性存储的字典中(请参见下面的代码)。字典包含键控到按钮的
UIViewController
实例。这个想法是,当按下五个按钮中的一个时,它将调用选择器
changeView:
,该选择器将从字典中检索相应的
UIViewController
实例并显示其视图

    self.viewControllersKeyedToButtons = [NSDictionary dictionaryWithObjectsAndKeys:

                                          rootViewController,
                                          button1,

                                          [[SYViewController_Feed alloc] init],
                                          button2,

                                          [[SYViewController_Capture alloc] init],
                                          button3,

                                          [[SYViewController_Likes alloc] init],
                                          button4,

                                          [[SYViewController_Profile alloc] init],
                                          button5,

                                          nil];
当我初始化字典时,我的代码就崩溃了。我收到以下错误消息:

2012-12-27 02:54:28.498 Smuvy[17931:c07]-[UIButton copyWithZone:]:发送到实例0x717fc10的选择器无法识别 2012-12-27 02:54:28.500 Smuvy[17931:c07]*由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[UIButton copyWithZone:::]:无法识别的选择器发送到实例0x717fc10' *第一次抛出调用堆栈: (0x174c012 0x1223e7e 0x17d74bd 0x173bbbc 0x173b94e 0x17ce714 0x1712b55 0x172d5a8 0x65d6 0x2c6e 0x1687b7 0x168da7 0x169fab 0x17b315 0x17c24b 0x16dcf8 0x3676df9 0x3676ad0 0x16c1bf5 0x16c1962 0x16f2bb6 0x16f1f44 0x16f1e1b 0x1697da 0x16b65c 0x2aad 0x29d5) libc++abi.dylib:terminate调用引发异常 (lldb)

现在是个谜。当我在调试器中跟踪变量
button5
时,我注意到在我尝试实例化字典之前,它就消失了!难怪我收到了一条错误消息

由于我是Objective-C(和C)的新手,我对内存管理知之甚少,我想我的变量出了问题。我运行过一些工具,有趣的是,我看到所有的
UIButton
实例都很活跃。因此,似乎按钮就在那里,只是指针不知何故失灵了


如果您能提供任何帮助,我们将不胜感激。

错误消息表示消息被发送到无法处理该消息的对象。在您的情况下,
copyWithZone:
被发送到
ui按钮的实例
copyWithZone:
是在
NSCopying
协议中声明的方法,但UIButton不采用该协议


发送此特定消息是因为您正在向NSDictionary添加一个条目,其中UIButton作为键。如中所述,复制密钥(使用copyWithZone:;密钥必须符合NSCopying协议),并将副本添加到新词典中。

创建NSDictionary时,通过调用
-copy
,调用
-copyWithZone:
。这些方法是协议的一部分

不幸的是,UIButton不符合该协议。它是不可复制的。当NSDictionary尝试向其发送
-copy
消息时,会引发异常,正如您所发现的那样

备选方案:

  • 改用一个字母

  • 使用或将键包装在NSValue中。(如果使用ARC,NSValue将无法确保保留对象,因此需要以其他方式对对象进行强引用。)

  • 使用其他方法确定视图控制器和UIButton可以共享的键。(例如,让它们都引用同一个字符串。)

  • 根本不用地图。也许可以将视图控制器保留在一个数组中,并使用ui按钮上的
    标记
    ,将相应视图控制器的索引存储在数组中


    • 这里有两个错误

      首先,在NSDictionary的文档中,声明其密钥必须符合
      协议,即。E它们应该响应
      copyWithZone:
      ,因为键在插入字典时会被复制。(这仅适用于键,相应的对象不需要可复制。)发生异常是因为
      UIButton
      (它只是
      UIControl
      UIView
      的子类)未实现此方法(如果您读取错误消息,它将被清除)

      因此,您不能将按钮用作字典中的键-如果您需要按钮和视图控制器之间的关联(顺便说一句,我怀疑这里存在设计问题,这个解决方案似乎相当粗糙),请为按钮和视图控制器使用单独的键,例如,使用简单的线性搜索来查找对应按钮的视图控制器


      或者,如果您不怕使用CoreFoundation,您可以使用
      CFDictionary
      (它与
      NSDictionary
      免费桥接)并提供一个不复制密钥的适当自定义密钥回调。

      您所说的“它消失”是什么意思?从源代码还是什么?另外,了解
      APPEND_STRING()
      宏的作用也很有用。我的意思是,当我在调试器窗格中跟踪它时,它从窗格中消失了。
      APPEND_STRING()
      宏只是连接两个字符串的简写:
      定义APPEND_STRING(string1,string2)[NSString stringWithFormat:@“%@”,string1,string2]
      好的:这是解决方案