【发布时间】:2011-06-27 13:37:25
【问题描述】:
我正在使用 Instruments 运行一个非常基本的测试应用程序,它发现了很多内存泄漏!由于我知道 Apple 人员在将应用程序提交到 iTunes 时会检查内存泄漏,所以我想调查一下这个问题。
我的环境:Mac OS X 10.6.6 上的 MonoDevelop 2.4.2 和 MonoTouch 3.2.4,目标是运行 iOS 4.2.1 的 iPad。
我的测试应用只显示了一个 TableView,其中填充了 50 个字符串的列表,并按它们的起始字母分组。
重现问题的步骤:使用 MonoDevelop 创建一个新的“基于 iPad 窗口的项目”,使用 Interface Builder 打开 MainWindow.xib 文件,在窗口上放置一个新的 TableView 并创建其出口(名为“tview”)以AppDelegate 类。 然后在Main.cs中输入如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace SimpleTable
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
public partial class AppDelegate : UIApplicationDelegate
{
private List<string> _names;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
_names = new List<string> { "Smith", "Jones", "Williams", "Brown", "Taylor",
"Davies", "Wilson", "Evans", "Thomas", "Johnson",
"Roberts", "Walker", "Wright", "Robinson", "Thompson",
"White", "Hughes", "Edwards", "Green", "Hall",
"Wood", "Harris", "Lewis", "Martin", "Jackson",
"Clarke", "Clark", "Turner", "Hill", "Scott",
"Cooper", "Morris", "Ward", "Moore", "King",
"Watson", "Baker", "Harrison", "Morgan", "Patel",
"Young", "Allen", "Mitchell", "James", "Anderson",
"Phillips", "Lee", "Bell", "Parker", "Davis" };
tview.Source = new MyTableViewSource(_names);
window.MakeKeyAndVisible ();
return true;
}
private class MyTableViewSource : UITableViewSource
{
private List<string> _sectionTitles;
private SortedDictionary<int, List<string>> _sectionElements = new SortedDictionary<int, List<string>>();
public MyTableViewSource(List<string> list)
{
// Use LINQ to find the distinct set of alphabet characters required.
_sectionTitles = (from c in list select c.Substring(0, 1)).Distinct().ToList();
// Sort the list alphabetically.
_sectionTitles.Sort();
// Add each element to the List<string> according to the letter it starts with
// in the SortedDictionary<int, List<string>>.
foreach (string element in list)
{
int sectionNum = _sectionTitles.IndexOf(element.Substring(0, 1));
if (_sectionElements.ContainsKey(sectionNum))
{
// SortedDictionary already contains a List<string> for that letter.
_sectionElements[sectionNum].Add(element);
}
else
{
// First time that letter has appeared, create new List<string> in the SortedDictionary.
_sectionElements.Add(sectionNum, new List<string> { element });
}
}
}
public override int NumberOfSections(UITableView tableView)
{
return _sectionTitles.Count;
}
public override string TitleForHeader(UITableView tableView, int section)
{
return _sectionTitles[section];
}
public override int RowsInSection(UITableView tableview, int section)
{
return _sectionElements[section].Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
string kCellIdentifier = "mycell";
UITableViewCell cell = tableView.DequeueReusableCell(kCellIdentifier);
if (cell == null)
{
// No re-usable cell found, create a new one.
cell = new UITableViewCell(UITableViewCellStyle.Default, kCellIdentifier);
}
string display = _sectionElements[indexPath.Section][indexPath.Row];
cell.TextLabel.Text = display;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
string display = _sectionElements[indexPath.Section][indexPath.Row];
showAlert("RowSelected", "You selected: \"" + display + "\"");
// Prevent the blue 'selection indicator' remaining.
tableView.DeselectRow(indexPath, true);
}
private void showAlert(string title, string message)
{
using (var alert = new UIAlertView(title, message, null, "OK", null))
{
alert.Show();
}
}
}
}
}
我在设备上进行了以下测试:
-
注释掉
public override string TitleForHeader(UITableView tableView, int section)程序,从 Instruments 内启动 App:发现单个泄漏;似乎这种泄漏总是存在,即使在测试一个空的应用程序时也是如此!
-
未注释
public override string TitleForHeader(UITableView tableView, int section)过程,从 Instruments 中启动应用程序:发现大量泄漏,并且当上下滚动表格和/或选择任何行时,泄漏的数量会增加。
-
替换
return _sectionTitles[section];声明
public override string TitleForHeader(UITableView tableView, int section)过程
return "Test Header…";(因此使用常量字符串):与测试 n.2 中的相同!
是 MonoTouch 出了问题还是我忘记了一些重要的东西?如果即使是这样一个简单的应用程序在运行几分钟后也会产生数百次内存泄漏,那么一个真正的(并且更复杂的)应用程序会发生什么?
我已经广泛搜索了网络,但我没有找到任何关于这个问题的重要帖子......任何贡献都将不胜感激。
【问题讨论】:
-
仅供参考;您的屏幕截图无效
标签: memory-leaks xamarin.ios instruments