NSURLConnection 上的 Apple SDK 文档中存在错误或混淆?

Posted

技术标签:

【中文标题】NSURLConnection 上的 Apple SDK 文档中存在错误或混淆?【英文标题】:Mistake or confusion in Apple SDK documentation on NSURLConnection? 【发布时间】:2009-05-07 01:38:56 【问题描述】:

我最近一直在学习 Apple SDK(适用于 iPhone 等),但遇到了一些我无法理解的东西。在来自http://developer.apple.com/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html的“使用 NSURLConnection”的文档中

我发现了一段奇怪的解释和示例代码。首先,它说:

在收到 initWithRequest:delegate: 消息后立即开始下载。可以在代理收到 connectionDidFinishLoading: 或 connection:didFailWithError: 消息之前的任何时间通过向连接发送取消消息来取消它。

接下来,它显示了以下代码:

NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 如果(连接) // 创建将保存的 NSMutableData //接收到的数据 // receivedData 在别处被声明为方法实例 receivedData=[[NSMutableData 数据] 保留]; 别的 // 通知用户无法下载

因此,在我看来,一旦连接初始化,下载必须立即在不同的线程中开始。这很清楚,因为代码是非阻塞的,并将消息发送回委托,在本例中为 self。然而,receivedData 的(自动释放样式)分配发生在 另一个线程启动之后。这不是不安全的比赛条件吗?如果服务器响应非常快(例如通过环回设备)或线程调度不顺利,这不会导致崩溃、内存泄漏或数据丢失吗?在初始化theConnection之前分配receivedData,然后在上面的else情况下释放它不是更有意义吗?

我被这段代码弄糊涂了,希望有人能帮我解释一下。 感谢您提供任何信息,

鲁迪·西里布拉西

【问题讨论】:

【参考方案1】:

没有竞争条件。下载在单独的线程上在后台启动,但发送给代理以通知您下载进度的消息始终在启动下载的线程上调用。

如果您更清楚的话,您当然可以在创建连接之前分配 NSData。您甚至可以在 connection:didReceiveData: 方法中分配它,如果您想确保除非有数据要存储,否则不会分配 NSData。

我认为示例的编写方式是为了使其尽可能简短,以免将演示文稿与大量不相关的代码混淆。

来自the documentation for NSURLConnection:

NSURLConnection 的委托方法 允许对象接收 关于的信息回调 URL 请求的异步加载。 其他委托方法提供 允许代表的设施 自定义执行的过程 异步 URL 加载。

请注意,这些委托方法将 在启动的线程上调用 异步加载操作 关联的 NSURLConnection 对象。

【讨论】:

这是有道理的。您能否提供一个支持所有委托消息都通过主线程发送的主张的 URL,以供我学习?感谢您的帮助和信息。 另外有趣的是 NSURLConnection 的委托消息是通过运行循环编组的,因此只有在控制权返回给它时才会发生。 非常感谢 Mark Bessey 和 rpetrich 的帮助。这对我来说非常清楚,我很感激。【参考方案2】:

这里没有竞争条件。 NSURLConnection 使用 NSRunLoop 来调度其事件。因此,在下一个事件循环开始之前,没有数据可以到达您的手中。

这意味着在下一个事件循环之前不会调用connection:didReceiveData:,无论数据何时真正返回,并且将在开始加载的线程上调用connection:didReceiveData:。所以你有这个运行循环的其余部分来让一切井井有条。 “立即”在这里的意思是“你不需要做任何事情来启动它。”

这不是推测或可变的实现细节;它基于 Cocoa 的设计原则。为了更好地理解 Cocoa,假设几乎所有事情都发生在主线程上。虽然框架可能偶尔会产生线程作为实现细节,但它们总是会提供一种它们没有的错觉。因此,就其性质而言,异步操作将始终出现在稍后的事件循环中。 Cocoa 的方式是合作而非抢占式多任务处理。

【讨论】:

这将教会我在真正响应某事之前让我的浏览器窗口打开这么久......是的,我刚刚完全重复了马克,他有正确的答案。 赞成,因为你添加了一些关于 NSRunLoop 的额外细节,我不太明白。 谢谢。我最初误入了这个线程来查找其他内容,但它提出了一些我很好奇的有趣问题,您的回答写得很好,内容丰富且令人愉​​快——我最喜欢最后一行,因为它解决了我自己关于一个线程如何在不破坏事情的情况下触发另一个线程中的事件的突然想法(我在想先发制人,但合作......这是有道理的)。

以上是关于NSURLConnection 上的 Apple SDK 文档中存在错误或混淆?的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking/NSURLConnection HTTPS 保持活动显示奇怪的行为

NSURLConnection的使用

https 上的 NSURLConnection 同步请求

清除 iOS 应用程序上的 NSUrlConnection 缓存?

应用程序在后台时的 NSURLConnection

ios:NSURLConnection sendAsynchronousRequest 为啥不起作用?