Ios 在混合Swift Objective-C环境中调用NSURLConnection时无响应

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

我已经创建了StartConnection类来处理我的NSURL请求。它被我的AppDelegate调用了两次,效果很好。它也被另一个类调用,这也很有效。这是StartConnection的实现:

#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
}