Ios 在混合Swift Objective-C环境中调用NSURLConnection时无响应
我已经创建了StartConnection类来处理我的NSURL请求。它被我的AppDelegate调用了两次,效果很好。它也被另一个类调用,这也很有效。这是StartConnection的实现:Ios 在混合Swift Objective-C环境中调用NSURLConnection时无响应,ios,objective-c,swift,nsurlconnection,Ios,Objective C,Swift,Nsurlconnection,我已经创建了StartConnection类来处理我的NSURL请求。它被我的AppDelegate调用了两次,效果很好。它也被另一个类调用,这也很有效。这是StartConnection的实现: #import "StartConnection.h" #import "BlaBlaBlog-swift.h" @implementation StartConnection { BOOL startedForBlog; } - (void)getRssFileWithUrl: (NSS
#import "StartConnection.h"
#import "BlaBlaBlog-swift.h"
@implementation StartConnection
{
BOOL startedForBlog;
}
- (void)getRssFileWithUrl: (NSString*)rssUrlString forBlog:(BOOL)forBlog
{
startedForBlog = forBlog;
NSURL *url = [NSURL URLWithString:rssUrlString];
NSURLRequest *rssRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:rssRequest delegate:self];
[connection start];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
dataSize = [response expectedContentLength];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (receivedData==nil )
{
receivedData = [[NSMutableData alloc]init];
}
// Append the new data to the instance variable you declared
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.receivedDataComplete = receivedData;
if (startedForBlog){
[self.delegate performSelector: @selector(receiveDataCompleted)];
}
else
[self.delegate performSelector: @selector(receivePodCastDataCompleted)];
}
为了亲身体验SWIFT,我在代码中添加了一个实验性的SWIFT类,该类也使用StartConnection.h。在调试器中,我可以看到正在创建StartConnection的实例,并且getFileWithUrl方法似乎被踢出了正常状态。但这就是所发生的一切。没有调用任何委托方法
这是SWIFT类:
import UIKit
class CheckActuality: NSObject, GetReceivedDataProtocol, WordPressParserDelegate {
var retrievePostData = StartConnection()
var parseCompleted: Bool=false
var result: Bool = true
lazy var wpParser = WordPressParser()
lazy var defaults = NSUserDefaults.standardUserDefaults()
func isActual () -> Bool {
var url = "http://blablablog.nl/new_api.php?function=get_recent_posts&count=1"
self.retrievePostData.delegate=self
self.retrievePostData.getRssFileWithUrl(url, forBlog:true)
while !self.parseCompleted
{
// wait till wpparser has completed
}
if self.wpParser.arrayWithPostDictionaries.count == 1
// Some info has been retrieved
{
var posts: NSArray = wpParser.arrayWithPostDictionaries
var post: NSDictionary = posts.objectAtIndex(0) as NSDictionary
var latestPostUrl: String = post.objectForKey("postUrl") as String
var currentLatestPostUrl = defaults.stringForKey("ttt")
if latestPostUrl != currentLatestPostUrl {
result = false
}
else {
result = true
}
}
return result
}
func receiveDataCompleted () {
if self.retrievePostData.receivedDataComplete != nil
{
self.wpParser.delegate=self
self.wpParser.parseData(retrievePostData.receivedDataComplete)
}
else
{
// warning no internet
}
}
func wpParseCompleted () {
self.parseCompleted=true
}
}
完整地说,my AppDelegate中的调用如下所示:
//
// retrieving PostData. Create a connection, set delegate to self en start with created url
//
retrievePostData = [[StartConnection alloc]init];
retrievePostData.delegate = self;
NSString *url = [[wordPressUrl stringByAppendingString:apiString] stringByAppendingString:pageCountString];
[retrievePostData getRssFileWithUrl:url forBlog:(BOOL)true];
//
// retrieving PodcastData. Create a connection, set delegate to self en start with created url
//
retrievePodCastData = [[StartConnection alloc]init];
retrievePodCastData.delegate = self;
[retrievePodCastData getRssFileWithUrl:podcastUrl forBlog:(BOOL)false];
我几乎一天都在发疯。希望你们中一些更有经验的人能帮助这个初学者。代码>同时!parseCompleted循环将阻塞主线程,直到下载和解析完成。但是接收数据的处理也发生在主线程上,因此如果该线程被阻塞,您的应用程序将处于死锁状态 我将消除
while
循环,并将所有后处理放在receivedDataComplete
方法中
顺便说一句,这个变化隐含的事实是,
isActual
必须是一个异步方法。因此,与其返回Bool
值,它应该是Void
返回类型,但您应该使用completionHandler
模式(我将其更改为也返回错误对象):
现在,我不知道latestPost
是否是您试图返回的值的合适名称,所以请将其更改为对您的例程有意义的名称。另外,名称是实际的
没有意义,但我会让您更改为您想要的任何名称
无论如何,当您使用它时,您应该使用尾部闭包语法来指定将异步执行的completionHandler
块:
let checkActuality = CheckActuality()
func someFunc() {
checkActuality.isActual() { latestPost, error in
if error != nil {
// do whatever error handling you want
println(error)
} else if latestPost {
// yes, latest post
} else {
// nope
}
}
// note, do not try to check `latestPost` here because the
// above closure runs asynchronously
}
不用说,这是一种
completionHandler
模式,但看看您的代码,您似乎更喜欢delegate
模式。如果您想使用委托
模式实现此功能,您可以。但是想法是一样的:这个isActual
方法(不管你最终将其重命名为什么)是异步运行的,所以你必须在完成后通知调用者。不要在你的连接上调用start
。initWithRequest
将为您启动它,因此您将启动它两次。调用start
的唯一时间是,如果您想在启动连接之前对连接进行一些自定义(例如,在某个特定的运行循环中安排连接),请立即使用startimely
选项no。非常感谢您花时间回答我的问题。我从你们身上学到了很多!总有一天我会报答:-)
let checkActuality = CheckActuality()
func someFunc() {
checkActuality.isActual() { latestPost, error in
if error != nil {
// do whatever error handling you want
println(error)
} else if latestPost {
// yes, latest post
} else {
// nope
}
}
// note, do not try to check `latestPost` here because the
// above closure runs asynchronously
}