我对运行方法具有以下代码,该方法返回由在单独的UIImage
类文件中创建的UIView
制成的UIView
。 FlagMarkerView
是UIView
的单独子类,在此引用。问题是FlagMarker *markerView...
行引发以下主线程检查器错误,并使应用程序崩溃。
UIView.init(coder :)必须在主线程中使用。
该代码原样工作,但由于我已将该项目更新为针对iOS 11的方式而不再工作。
我尝试将FlagMarkerView
调用包装在dispatch_async(dispatch_get_main_queue(), ^{});
中,但这不起作用,因为该方法不会被返回UIImage
接收。我也尝试使用-(void)
方法而不是返回UIImage
,但这对我的项目的复杂性有危害。
[有没有一种方法可以在newMarkerImage
中创建- (void)updateMyFlagsWitAlert:
并将dispatch_async(dispatch_get_main_queue(), ^{
用于FlagMarkerView
,以便可以从newMarkerImage
的行中创建markerImage
。
- (void)updateMyFlagsWitAlert:(BOOL)isAllowed{
for (AGSGraphic *graphic in weakSelf.flagOverlay.graphics) {
FlagModel *flagToUpdate = graphic.attributes[@"flag"];
UIImage *newMarkerImage =
[weakSelf markerImageForFlag:flagToUpdate withDetail:detail];
}
}
- (UIImage *)markerImageForFlag:(FlagModel *)flag withDetail:(BOOL)withDetail {
// This line crashes app
FlagMarkerView *markerView = [[[NSBundle mainBundle] loadNibNamed:@"FlagMarkerView" owner:self options:nil] objectAtIndex:0];
[markerView setFlag:flag];
UIImage *markerImage = [markerView imageWithDetail:withDetail];
[markerView layoutIfNeeded];
return markerImage;
}
您可能应该重新设计代码以使其异步,但是我能想到的最快方法是:
__block FlagMarkerView *markerView;
dispatch_sync(dispatch_get_main_queue(), ^{
markerView = [[[NSBundle mainBundle] loadNibNamed:@"FlagMarkerView" owner:self options:nil] objectAtIndex:0];
[markerView setFlag:flag];
UIImage *markerImage = [markerView imageWithDetail:withDetail];
[markerView layoutIfNeeded];
});
return markerImage;
这将使您的代码在主线程中运行,并等待其完成。这不是一个好的设计,您应该设计更好的代码,而不要依赖于返回值。相反,您的代码可以使用块作为参数,该参数将在主线程中处理结果后接收结果,而不是使用信号量等待结果。但是有时候,如果您只需要一些工作,此解决方案可能会有所帮助。
以下代码更改解决了我的问题。我发现问题根本不在markerImageForFlag
,即使主线程检查器突出显示了markerView
。我相信weakSelf
参考将任务放在了后台线程上,这已经可以使用一段时间了,但是现在不再起作用了。我要做的只是放dispatch_sync
,而不是dispatch_async', on the call,
newMarkerImage`。感谢@Rob和@Moshe!见下文。
- (void)updateMyFlagsWitAlert:(BOOL)isAllowed{
for (AGSGraphic *graphic in weakSelf.flagOverlay.graphics) {
FlagModel *flagToUpdate = graphic.attributes[@"flag"];
__block UIImage *newMarkerImage = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
newMarkerImage = [weakSelf markerImageForFlag:flagToUpdate withDetail:(scale < markerThreshold)];
});
}
}