gpt4 book ai didi

ios - 拉动刷新崩溃应用程序

转载 作者:行者123 更新时间:2023-11-28 20:12:21 24 4
gpt4 key购买 nike

我有一个应用程序,它从 3 个共享的 Google 日历中获取事件并将其显示在表格 View 中。

我想实现拉动刷新,但如果我在加载数据之前松开拉动,应用程序会一直崩溃。 (如果我拉动几秒钟,一切都很好 - 如果我立即松手,它就会崩溃。

代码:

-(void)viewDidLoad
{
[super viewDidLoad];
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
[refresh addTarget:self action:@selector(getEvents) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
startDates = [[NSMutableArray alloc] init];
[self getEvents];
}

- (void)stopRefresh
{
[self.refreshControl endRefreshing];
}

-(void)getEvents
{
[startDates removeAllObjects];
startDates = [NSMutableArray array];
sectionEntries = [NSMutableArray array];
entries = [NSMutableArray array];
sortedStartDates = [[NSArray alloc]init];
_imageForCalendarType = [[NSDictionary alloc]init];
_imageForCalendarType = @{
@"The Irish House Music Calendar" : [UIImage imageNamed:@"music.png"]
, @"FixedEvents-Student Night" : [UIImage imageNamed:@"student.png"]
, @"FixedEvents-Ladies Night" : [UIImage imageNamed:@"cocktail.png"]
, @"AppTest" : [UIImage imageNamed:@"football.png"]
};
dispatch_async(kBgQueue, ^{

NSData* data = [NSData dataWithContentsOfURL:sportsCalendarURL];
[self performSelectorOnMainThread:@selector(fetchedData:) withObject:data waitUntilDone:YES];

NSData* data2 = [NSData dataWithContentsOfURL:musicCalendarURL];
[self performSelectorOnMainThread:@selector(fetchedData:) withObject:data2 waitUntilDone:YES];

NSData* data3 = [NSData dataWithContentsOfURL:fixedCalendarURL];
[self performSelectorOnMainThread:@selector(fetchedData:) withObject:data3 waitUntilDone:YES];

// Reload table view - UI operation, so must be run on main thread
dispatch_async(dispatch_get_main_queue(), ^{

sortedStartDates = [startDates sortedArrayUsingSelector:@selector(compare:)];
[self.tableView reloadData];
[self performSelector:@selector(stopRefresh) withObject:nil afterDelay:2.5];
});
});


}

它在 cellForRowAtIndexPath 方法的这一行中给我一个 SIGABRT 错误:

 NSInteger index = [self getRow:sortedStartDates[indexPath.section]];  // get correct index for sectionEntries

错误:* 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“* -[__NSArrayI objectAtIndex:]:索引 4 超出空数组的范围”

错误似乎是因为我的 startDates NSMutableArray 中没有数据,但是如果我注释行 [startDates removeAllObjects] 我会得到冗余单元格。

最佳答案

至少,我建议检查以确保刷新尚未在进行中。您可能还想更改 getEvents 以将刷新控件作为参数并相应地更新下拉列表(以便用户知道正在进行刷新):

- (void)viewDidLoad
{
[super viewDidLoad];

_imageForCalendarType = @{
@"The Irish House Music Calendar" : [UIImage imageNamed:@"music.png"]
, @"FixedEvents-Student Night" : [UIImage imageNamed:@"student.png"]
, @"FixedEvents-Ladies Night" : [UIImage imageNamed:@"cocktail.png"]
, @"AppTest" : [UIImage imageNamed:@"football.png"]
};

UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
[refresh addTarget:self action:@selector(getEvents:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
[self getEvents:refresh];
}

- (void)getEvents:(UIRefreshControl *)refresh
{
static BOOL refreshInProgress = NO;

if (!refreshInProgress)
{
refreshInProgress = YES;

refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing"]; // let the user know refresh is in progress

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// get the data here

dispatch_async(dispatch_get_main_queue(), ^{

// when done, update the model and the UI here

refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"]; // reset the message
[refresh endRefreshing];

refreshInProgress = NO;
});
});
}
}

但是,您应该非常小心地异步更新模型数据(因为您的主队列可能会在更新过程中尝试从模型中检索信息)。你真的应该推迟模型的更新,直到最后分派(dispatch)到主队列。但是不要在异步过程中更新模型,否则您的模型和 UI 可能会暂时处于不一致状态。

此外,作为一种改进,您可能希望同时检索这三个数据源,并且您可能会观察到明显的性能改进。

- (void)getEvents:(UIRefreshControl *)refresh
{
static BOOL refreshInProgress = NO;

if (!refreshInProgress)
{
refreshInProgress = YES;

refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing"]; // let the user know refresh is in progress

// get the data here

__block NSData *data1 = nil;
__block NSData *data2 = nil;
__block NSData *data3 = nil;

dispatch_queue_t queue = dispatch_queue_create([[[[NSBundle mainBundle] bundleIdentifier] stringByAppendingString:@".network"] UTF8String], DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{
data1 = [NSData dataWithContentsOfURL:sportsCalendarURL];
});

dispatch_async(queue, ^{
data2 = [NSData dataWithContentsOfURL:musicCalendarURL];
});

dispatch_async(queue, ^{
data3 = [NSData dataWithContentsOfURL:fixedCalendarURL];
});

// use dispatch barrier here, which will only fire when the previous three requests are done

dispatch_barrier_async(queue, ^{

// update the UI here

dispatch_async(dispatch_get_main_queue(), ^{

startDates = [NSMutableArray array];
sectionEntries = [NSMutableArray array];
entries = [NSMutableArray array];

[self fetchedData:data1];
[self fetchedData:data2];
[self fetchedData:data3];

refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"]; // reset the message
[refresh endRefreshing];

sortedStartDates = [startDates sortedArrayUsingSelector:@selector(compare:)];
[self.tableView reloadData];

refreshInProgress = NO;
});
});
}
}

如果您只有三个数据源,您可能可以使用 GCD 并发队列,但如果您可能有更多数据源,您可能想要使用一个操作队列,您可以在其中限制并发请求的数量。另外,您可以考虑使用 AFNetworking ,它可以更好地协调这些网络请求与您可能在其他地方同时进行的其他网络请求。

但是这里的主要观察结果是 (a) 在刷新完成并且您准备好更新 UI 之前不要更新您的模型; (b) 确保在前一个刷新正在进行时不启动新的刷新(或者,如果你真的需要它,移动到一个操作队列模型,在那里你制作可取消的 NSOperation 子类,然后理论上您可以在发出另一个更新请求之前取消先前的请求(如果有))。


与手头的问题完全无关,但在我的第一个代码片段中,您会看到我将 _imageForCalendarType 的设置移出此 block (因为您总是将其设置为同样的事情)并进入 viewDidLoad。我还删除了这个不必要的行:

_imageForCalendarType = [[NSDictionary alloc]init];

您在下一行中为字典文字丢弃了这个实例化的字典,因此不需要上面的行。

坦率地说,您可能甚至不应该拥有 UIImage 对象的字典,而只是图像名称的字典,并让 cellForRowAtIndexPath 实例化 UIImage 那里。当您只有三个图像时可能并不重要,但如果您有更多图像,则现有的 UIImage 对象构造数组在内存压力情况下可能会出现问题。是的,您可以插入适当的 didReceiveMemoryWarning 处理,但从不维护包含 UIImage 对象的字典要简单得多。

关于ios - 拉动刷新崩溃应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19683892/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com