从主线程iOS上的子类创建自定义UIView

问题描述 投票:0回答:2

我对运行方法具有以下代码,该方法返回由在单独的UIImage类文件中创建的UIView制成的UIViewFlagMarkerViewUIView的单独子类,在此引用。问题是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;
}

enter image description here

ios objective-c swift uiview
2个回答
1
投票

您可能应该重新设计代码以使其异步,但是我能想到的最快方法是:

    __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;

这将使您的代码在主线程中运行,并等待其完成。这不是一个好的设计,您应该设计更好的代码,而不要依赖于返回值。相反,您的代码可以使用块作为参数,该参数将在主线程中处理结果后接收结果,而不是使用信号量等待结果。但是有时候,如果您只需要一些工作,此解决方案可能会有所帮助。


0
投票

以下代码更改解决了我的问题。我发现问题根本不在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)];
        });

    }

}

© www.soinside.com 2019 - 2024. All rights reserved.