为测验应用程序创建工具栏
Posted
技术标签:
【中文标题】为测验应用程序创建工具栏【英文标题】:Create toolbar for quiz app 【发布时间】:2011-03-16 11:58:26 【问题描述】:这与我之前发布的一个问题有关。我仍然坚持它。这里有一个描述。我正在创建一个测验应用程序。它有一个工具栏,每次用户单击按钮时都会动态创建其按钮。我使用一种方法将三个按钮添加到一个数组中,然后使用 for 循环检查问题的选项数量,然后为每个选项创建一个按钮并将其添加到数组中。后来我使用@987654321 @
添加按钮
但是在执行此操作时,我遇到了内存泄漏。应用程序在 200 个问题后崩溃。我使用工具发现泄漏位于按钮创建区域。但是在做了很多实验后,我不知道该怎么做.
我还有一个问题
有没有办法找出由 iphone sdk.Specificaly 中的内置方法创建的对象的保留计数,
1)NSMutableArray的addobject方法是否增加了被添加对象的retain count 2)如果我打算释放存储在其中的customBarButtonItem 对象,[[toolbar items] release] 是否可能会造成麻烦?
因为使用这些选项,应用程序要么立即崩溃,要么更改对报告的泄漏没有影响
这是代码。它有很多注释行,这些都是我尝试过的选项
- (void)CreateButtons
UIToolbar *tempToolBar=[[UIToolbar alloc] ]
numberOfChoices=0;//set number of choice buttons at present to 0
NSMutableArray *tempItems=[[NSMutableArray alloc] init];//Array for holding the buttons
Question *question=[currentQuestion question];
NSString *answer=[question answerOptions];
int numericAnswer=0;
numericAnswer=[answer characterAtIndex:0];
//see if its a number or a character
if (numericAnswer > 96) // its a character
int choice;
for (choice=97; choice <=numericAnswer ; choice ++)
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:@"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:@"%c",(char)choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:@selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
if (isReviewing == TRUE)
customBarItem.customView.userInteractionEnabled=FALSE;
//Add button to the array
[tempItems addObject:customBarItem];
//release buttons
[customBarItem release];
numberOfChoices++;
else
int choice;
for (choice=49; choice<=numericAnswer; choice ++)
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:@"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:@"%c",choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:@selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
//Add button to the array
[tempItems addObject:customBarItem];
if (isReviewing == TRUE)
customBarItem.customView.userInteractionEnabled=FALSE;
//release buttons
[customBarItem release];
numberOfChoices++;
//load the image
UIButton *previousButton = [UIButton buttonWithType:UIButtonTypeCustom];
[previousButton setBackgroundImage:[UIImage imageNamed:@"prev.png"] forState:UIControlStateNormal];
[previousButton addTarget:self action:@selector(PreviousClicked:) forControlEvents:UIControlEventTouchUpInside];
previousButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem6 = [[UIBarButtonItem alloc] initWithCustomView:previousButton];
//[previousButton release];
self.prevButton=customBarItem6;
UIButton *nextButton= [UIButton buttonWithType:UIButtonTypeCustom];
[nextButton setBackgroundImage:[UIImage imageNamed:@"nex.png"] forState:UIControlStateNormal];
[nextButton addTarget:self action:@selector(nextClicked:) forControlEvents:UIControlEventTouchUpInside];
nextButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH, TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem7 = [[UIBarButtonItem alloc] initWithCustomView:nextButton];
//[nextButton release];
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[tempItems addObject:flexItem];
[tempItems addObject:customBarItem6];
[tempItems addObject:customBarItem7];
//release buttons
[customBarItem6 release];
[customBarItem7 release];
[flexItem release];
//NSArray *items=[[NSArray alloc] initWithArray:(NSArray *)tempItems];
//[tempItems release];
//add array of buttons to toolbar
//if([[toolbar items] count]>0)
// // [[工具栏项] 发布]; // [工具栏设置项目:临时项目动画:是]; //[物品发布]; //[self.view addSubview:toolbar]; if(isReviewing == FALSE && isPractice == FALSE)
prevButton.enabled=FALSE;
//[toolbar bringSubviewToFront:customBarItem6.customView];
工具栏是通过 ib 创建的
是的,它有很多代码,但它只是根据问题的选择数创建按钮。这两个 for 循环是相似的,除了一个在按钮上放置 a、b、c、d 而另一个放置 1,2 ,3,4.....另外创建了三个按钮。一个用于下一个,上一个和一个弹性项目。每次用户单击下一个按钮时都会调用此方法。
【问题讨论】:
如果您不想要以前的问题或选项,您可以尝试从可变数组中删除它们。并请发布一些代码。 有一些 tempArray 的代码吗? 【参考方案1】:我可以看到一些内存效率不是很高的东西:
-
您使用了很多便利的初始化程序:
buttonWithType
和 'imageNamed`。这些将在将来的某个时候自动释放,但不在您的方法中。
项目tempToolbar
已分配但从未释放。这会泄漏。
您的可变数组 tempItems
似乎也没有被释放:这将彻底杀死您,因为您的所有按钮都已添加到其中...
基于此,我建议:
-
使用 alloc/init 方法代替便捷构造函数
或者:在方法的开头创建
NSAutoReleasePool
,在结尾创建drain
:这将释放所有自动释放的实体。
祝你好运
【讨论】:
我将 tempArray 作为类变量。现在仪器不显示任何泄漏。希望一切顺利 @mithun。您是在两次调用之间清空它还是继续向它添加对象而不释放它。它是否是类成员都没有关系。重要的是要添加到其中的所有对象都由数组保留。除非您释放数组中的所有项目或释放数组本身,否则您永远不会释放这些对象持有的内存。 在检查计数为 0 后,我在每次调用中使用 removeAllObjects 方法 @mithun。这应该适用于这个。另一个项目tempToolbar
怎么样?您还应该在调用该方法时查看您的内存占用情况。内存使用量是否在增长?最后关于泄漏检测,您多久进行一次泄漏取样?最后一件事:您用于按钮的图像有多大?
图像为 4KB。我每 10 秒采样一次。根据我的理解,内存使用量没有增长。没有泄漏。每次激增后分配图下降到零。希望一切都好【参考方案2】:
很难遵循所有这些代码,但对于 1) 的简单部分答案是,是的,[NSMutableArray addObject:]
增加保留 +1。
【讨论】:
是的,它有很多代码,但它只是根据问题的选择数量创建按钮。两个 for 循环是相似的,除了一个将 a、b、c、d 放在按钮上,而另一个one puts 1,2,3,4.....另外创建了三个按钮。一个用于下一个,上一个和一个弹性项目。每次用户单击下一个按钮时都会调用此方法。以上是关于为测验应用程序创建工具栏的主要内容,如果未能解决你的问题,请参考以下文章