无法使用块在 UITableViewCell 中设置 UIButton 标题
can't set UIButton title in UITableViewCell with block
我在自定义 UITableViewCell
中有一个 UIButton
,当我按下按钮时,它会 post 使用 AFNetworking
将数据发送到我的服务器,在成功块中我设置一个新的按钮标题,但它不起作用。
在 CutomTableViewCell
中,我使用了一种协议,因此我可以响应按钮点击:
@implementation SubjectReplyCell
- (IBAction)btnReplyPressed:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(postData:atIndex:)]) {
[self.delegate postData:self atIndex:sender.tag];
}
}
@end
然后我将委托和 post 数据实现到服务器:
@implementation BBSDetailsController
- (void)postData:(SubjectReplyCell *)cell atIndex:(NSInteger)idx {
urlString = [API_HOST stringByAppendingString:BBS_PRAISE_OPPOSITION];
__weak typeof(SubjectReplyCell) *weakCell = cell;
[requestManager POST:urlString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject[@"returnode"] isEqualToString:@"success"]) {
//it doesn't work
[weakCell.btnReply setTitle:@"newTitle" forState:UIControlStateNormal];
[weakCell setNeedsLayout];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
但是,如果我将标题设置为块外,效果很好:
- (void)postData:(SubjectReplyCell *)cell atIndex:(NSInteger)idx {
urlString = [API_HOST stringByAppendingString:BBS_PRAISE_OPPOSITION];
//it work
[cell.btnReply setTitle:@"newTitle" forState:UIControlStateNormal];
[requestManager POST:urlString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject[@"returnode"] isEqualToString:@"success"]) {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
AFNetworking 默认使用主队列处理失败和完成块,因此您无需担心为 UI 更改调用主线程。 See this answer
如果要修改块内的对象,则需要使用 __block
关键字(即两个下划线)。使用 __block
提前告诉编译器您计划在块内改变对象,因此请区别对待此对象以保留更改。
所以这个:
__weak typeof(SubjectReplyCell) *weakCell = cell;
应该是这样的:
__block typeof(SubjectReplyCell) *weakCell = cell;
编辑:
您不需要在您的单元格上使用 __weak
,因为在此块中修改您的单元格不应创建引用循环。在这种情况下,您的单元格将保留在完成块中,但单元格不会保留块本身,因此这两者不会创建保留循环。
你需要使用__weak
,如果两个对象在游戏中有可能导致一个保留循环,比如当你在一个块中捕获 self 并且该块也被 self 捕获时。 Here's another answer for some more clarity
我在自定义 UITableViewCell
中有一个 UIButton
,当我按下按钮时,它会 post 使用 AFNetworking
将数据发送到我的服务器,在成功块中我设置一个新的按钮标题,但它不起作用。
在 CutomTableViewCell
中,我使用了一种协议,因此我可以响应按钮点击:
@implementation SubjectReplyCell
- (IBAction)btnReplyPressed:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(postData:atIndex:)]) {
[self.delegate postData:self atIndex:sender.tag];
}
}
@end
然后我将委托和 post 数据实现到服务器:
@implementation BBSDetailsController
- (void)postData:(SubjectReplyCell *)cell atIndex:(NSInteger)idx {
urlString = [API_HOST stringByAppendingString:BBS_PRAISE_OPPOSITION];
__weak typeof(SubjectReplyCell) *weakCell = cell;
[requestManager POST:urlString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject[@"returnode"] isEqualToString:@"success"]) {
//it doesn't work
[weakCell.btnReply setTitle:@"newTitle" forState:UIControlStateNormal];
[weakCell setNeedsLayout];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
但是,如果我将标题设置为块外,效果很好:
- (void)postData:(SubjectReplyCell *)cell atIndex:(NSInteger)idx {
urlString = [API_HOST stringByAppendingString:BBS_PRAISE_OPPOSITION];
//it work
[cell.btnReply setTitle:@"newTitle" forState:UIControlStateNormal];
[requestManager POST:urlString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject[@"returnode"] isEqualToString:@"success"]) {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
AFNetworking 默认使用主队列处理失败和完成块,因此您无需担心为 UI 更改调用主线程。 See this answer
如果要修改块内的对象,则需要使用 __block
关键字(即两个下划线)。使用 __block
提前告诉编译器您计划在块内改变对象,因此请区别对待此对象以保留更改。
所以这个:
__weak typeof(SubjectReplyCell) *weakCell = cell;
应该是这样的:
__block typeof(SubjectReplyCell) *weakCell = cell;
编辑:
您不需要在您的单元格上使用 __weak
,因为在此块中修改您的单元格不应创建引用循环。在这种情况下,您的单元格将保留在完成块中,但单元格不会保留块本身,因此这两者不会创建保留循环。
你需要使用__weak
,如果两个对象在游戏中有可能导致一个保留循环,比如当你在一个块中捕获 self 并且该块也被 self 捕获时。 Here's another answer for some more clarity