gpt4 book ai didi

ios - iphone nsoperation 应用程序卡住

转载 作者:行者123 更新时间:2023-11-28 22:20:55 25 4
gpt4 key购买 nike

我做了一个 NSOperation 的子类,叫做 ˚ 来实现多部电影下载。在 appDelegate.m 中,我创建了一个 NSOperationQueue 的对象。

- (void)applicationDidFinishLaunching:(UIApplication *)application {
queue = [[NSOperationQueue alloc] init];
[queue setMaximumConcurrentOperationCount:5]
}

MovieDownloadOperation 依赖于一个名为 Downloader 的类,它实际下载电影并提供回调 movieCompletelyDownloadedWithUrl: .
然后,我在 MovieDownloadOperation 中创建了一个名为 downloadState 的属性。它具有不同的值,例如 "STARTED""DOWNLOADING""COMPLETED""ERROR"

MyDownloadOperation 看起来像

-(id)initWithUrl:(NSURL *)url
{

if (self = [super init])
{
_downloader = [[Downloader alloc] initWithUrl:url];
_downloadState = @"STARTED" ;
}
}

-(void)main
{
while(1)
{
if ([_downloadState isEqualToString:@"COMPLETED"])
{
NSLog(@"movie downloaded successfully");
break ;
}
}

}

-(void)movieCompletelyDownloadedWithUrl:(NSURL *)url
{
_downloadState = @"COMPLETED" ;
}

这适用于一部电影,但当我尝试下载多部电影时,UI 会卡住,直到下载完第一部电影。我认为问题是 main 方法中的 while 循环,是否有更好的方法来检查 _downloadState 是否更改为 “完成” ??

最佳答案

目前尚不清楚为什么 UI 在执行多项操作时会卡住,但在一次下载时不会卡住。但是,您的代码示例引发了一些想法:

  1. 并发操作:

    而不是在 main 中有一个 while 循环,你通常会定义你的操作是并发的(即返回 YES是并发的)。然后 movieCompletelyDownloadedWithUrl 将发布 isFinished 事件,这将触发操作的完成。

    就如何进行并发操作而言,您可以定义executingfinished 的属性:

    @property (nonatomic, readwrite, getter = isFinished)  BOOL finished;
    @property (nonatomic, readwrite, getter = isExecuting) BOOL executing;

    您可能希望 URL 和下载器具有 strong 属性:

    @property (nonatomic, strong)               NSURL *url;
    @property (nonatomic, strong) Downloader *downloader;

    然后您可能在操作子类中有以下代码:

    @synthesize finished  = _finished;
    @synthesize executing = _executing;

    - (id)init
    {
    self = [super init];

    if (self) {
    _finished = NO;
    _executing = NO;
    }

    return self;
    }

    - (id)initWithUrl:(NSURL *)url
    {
    self = [self init];

    if (self) {
    // Note, do not start downloader here, but just save URL so that
    // when the operation starts, you have access to the URL.

    _url = url;
    }

    return self;
    }

    - (void)start
    {
    if ([self isCancelled]) {
    self.finished = YES;
    return;
    }

    self.executing = YES;

    [self main];
    }

    - (void)main
    {
    // start the download here

    self.downloader = [[Downloader alloc] initWithUrl:self.url];
    }

    - (void)completeOperation
    {
    self.executing = NO;
    self.finished = YES;
    }

    // you haven't shown how this is called, but I'm assuming you'll fix the downloader
    // to call this instance method when it's done

    - (void)movieCompletelyDownloadedWithUrl:(NSURL *)url
    {
    [self completeOperation];
    }

    #pragma mark - NSOperation methods

    - (BOOL)isConcurrent
    {
    return YES;
    }

    - (void)setExecuting:(BOOL)executing
    {
    [self willChangeValueForKey:@"isExecuting"];
    _executing = executing;
    [self didChangeValueForKey:@"isExecuting"];
    }

    - (void)setFinished:(BOOL)finished
    {
    [self willChangeValueForKey:@"isFinished"];
    _finished = finished;
    [self didChangeValueForKey:@"isFinished"];
    }

    因此,使用这些方法,您可以像上面那样让 movieCompletelyDownloadedWithUrl 调用 completeOperation,这将确保 isExecutingisFinished 通知被发布。您还想响应取消事件,确保在操作取消时取消下载。

    参见 Configuring Operations for Concurrent Execution 并发编程指南部分了解更多详细信息。

  2. 直到 main 才开始下载:

    我没有看到您的 main 方法启动下载。这让我感到紧张,因为您的 Downloader 初始化方法 initWithURL 可能正在启动下载,这很糟糕。您不希望在创建操作时启动下载,而是在操作开始之前不应该这样做(例如 startmain)。因此,在我上面的示例中,我只有 initWithURL 保存 URL,然后 main 开始下载。

  3. NSOperation 中使用 NSURLConnectionDataDelegate 方法:

    顺便说一句,您没有分享您的操作是如何处理网络请求的。如果您正在使用 NSURLConnectionDataDelegate 方法,当您摆脱 main 中的 while 循环时,如果不安排,您可能会遇到问题特定运行循环中的 NSURLConnection。例如,您可能会这样做:

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    [connection start];

    如果你没有使用 NSURLConnectionDataDelegate 方法,或者如果你已经解决了这个运行循环问题,那么忽略这个建议,但是,最重要的是,当你修复 main 方法,您可能会暴露旧 main 可能对您隐藏的 NSURLConnection 问题。

  4. Downloader 如何调用 moveCompleteDownloadedWithUrl

    顺便说一句,您没有展示Downloader 可能如何调用moveCompleteDownloadedWithUrl。这看起来很可疑,但我只是希望您在发布代码时能简化代码。但是,如果您没有使用协议(protocol)委托(delegate)模式或完成 block 模式,那么我会非常担心您的多个 Downloader 对象如何通知相应的 MyDownloadOperation 对象下载完成。就个人而言,我可能倾向于将这两个不同的类重构为一个类,但这是个人品味的问题。

关于ios - iphone nsoperation 应用程序卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20438378/

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