【问题标题】:Help with making NSURLConnection in a custom class帮助在自定义类中制作 NSURLConnection
【发布时间】:2026-01-26 16:30:01
【问题描述】:

大家好,我正在尝试使用 Yahoo 的 PlaceFinder 为我正在制作的应用程序进行反向地理编码。问题是我需要使用 NSURLConnection 来调用我的数据库。所以我决定做一个自定义类,用用户的经纬度进行初始化,只存储一个包含用户所在状态的字符串变量。

更新以下代码现在可以正常工作了....

这是.h

#import <Foundation/Foundation.h>
#import "CJSONDeserializer.h"

@interface StateFinder : NSObject 
{
    NSString *userState;
    NSURLConnection *connection;
}

-(id)initwithLatitude:(NSString *)latitude andLongitude:(NSString *)longitude;
@property (nonatomic, retain) NSString *userState;
@property (nonatomic, retain) NSURLConnection *connection;

@end

和.m

#import "StateFinder.h"

@implementation StateFinder

@synthesize userState;
@synthesize connection;

-(id)initwithLatitude:(NSString *)latitude andLongitude:(NSString *)longitude
{
    if(self = [super init])
    {
        NSString *lat = latitude;
        NSString *lon = longitude;

        NSString *stateURLFinder = [NSString stringWithFormat:@"http://where.yahooapis.com/geocode?q=%@,+%@&gflags=R&flags=J&appid=zqoGxo7k", lat, lon];

        //NSLog(stateURLFinder);

        NSURL *stateURL = [NSURL URLWithString:stateURLFinder];


        NSURLRequest *request = [[NSURLRequest alloc] initWithURL: stateURL];

        connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

        [request release];
    }
    return self;
}


-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse");
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"didFinishLoading");
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError");
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{
    // Store incoming data into a string
    NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    NSLog(jsonString);
    // Yes, this is incomplete, but I was waiting for the method to fire before going
        // any further. This will at least show me the JSON data being returned from yahoo 
        // in string format so I can output it to the console via NSLog
}

- (void)dealloc 
{
    [userState release];
    [connection release];
    [super dealloc];
}

@end

这是我正在使用的当前代码,它运行良好。我所做的只是在原始代码中包含 connectionDidFinishLoading 和 didFailWithError 方法。关于在建立之前释放的连接,我使用上面的代码没有前面提到的方法,并且 didReceiveData/didReceiveResponse 都不会命中。直到这两个方法被包含在内,这些方法才开始被调用。不知道如何,不知道为什么,但这是所有建议中唯一有效的变化。非常感谢@Jiva DeVoe、@XJones、@jlehr 和@Aby 提供的所有提示/提示/建议!

【问题讨论】:

  • 根据多个建议,我注释掉了连接的释放,即使它似乎在用于调用我的数据库的代码的其他部分中工作。通过注释掉这个版本,我仍然没有在这个类中使用 didReceiveData 或 didReceiveResponse 方法。还有其他建议吗?

标签: objective-c nsurlconnection


【解决方案1】:

其实我建议你绝对不要使用sendSynchronousRequest。您应该始终尝试使用异步网络,除非您正在开发的应用程序是没有运行循环的命令行应用程序。

我怀疑你的问题可能是你立即释放连接,所以它永远没有机会运行。您应该添加一个成员变量并保留它,直到您收到响应或其他任何内容。

额外提示:

猜测您可能正在为 iOS 或 Mac 执行此操作,并编写 GUI 应用程序。这些应用程序有运行循环。当您像先前的答案所建议的那样使用同步网络时,您会阻止该 runloop 执行。这意味着如果请求时间超过几秒钟,您的 iOS 应用程序将被操作系统杀死,您的 Mac 应用程序将显示为无响应。这些都不是好的结果。

【讨论】:

  • 嗯,据我了解,在 NSURLConnection 建立时会立即调用 didReceiveData。在我的视图控制器中,我的数据库调用是我上面编码的方式,它返回没有问题。
  • 就应用而言,它只会运行一次(自定义类在视图控制器的init方法中调用一次,自定义类内部的连接在自定义类内部的init方法中)同样,所以它永远不应该被多次调用。
  • 首先,是否多次调用都没关系。不确定您对此有何建议。其次,WRT didReceiveData 被立即调用......好吧,它在 NSURLConnection 获取数据后立即被调用......但是由于你立即释放 NSURLConnection ,它永远没有机会在 runloop 上运行,所以你永远不会甚至尝试建立连接。
  • 哦,还有,这里有很大的问题......不知道为什么我以前没有看到它......你的 init 方法完全错误。您需要执行以下操作: if((self = [super init])) { ... all your code there ... } 在里面。
  • 好的,我编辑了我的代码以包含您建议的 if 语句。此外,我试图简单地注释掉连接的释放(一旦我看到它工作就担心内存泄漏)并且 didReceiveData 仍然没有被调用。有什么想法为什么不会?
【解决方案2】:

在连接有机会运行之前,您正在向连接发送release 消息;不要那样做。关于JSON,你说的字符串是从服务器返回的 JSON。你期待别的吗?

【讨论】:

  • 好的,我把release注释掉了(我以后会担心内存泄漏的),但是didReceiveData仍然没有被调用。
【解决方案3】:

摆脱线:

[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

一旦您使用请求初始化连接,它就会自动运行。你还有其他问题。您对 NSURLConnectionDelegate 协议的实现是错误的。您需要将connection:didReceiveResponse 中收到的数据增量添加到 NSMutableData 对象。您可以在 `connectionDidFinishLoading:' 中将其转换为 JSON。

至于内存泄漏,释放connectionDidFinishLoading:connection:didFailWithError:中的连接,保证收到一个,但不能同时收到。

您需要知道的一切都是here

[编辑:添加 NSURLConnection 代码示例]

// Attach this to the touchUpInside event of a UIButton
// Note that all objects will be autoreleased
// Note that you can comment out any or all of the NSURLConnection delegate methods
// and the request will execute

- (IBAction)initiateRequest
{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL urlWithString:@"http://www.google.com"]];
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
}

- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)date
{
    NSLog(@"connection:didReceiveData");
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"connection:didReceiveResponse:");
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"connectionDidFinishLoading:");
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"connection:didFailWithError:");
}

【讨论】:

  • @XJones ,该连接线不是我最初在我的代码中使用的连接线,而是由另一位用户建议的。我把它加进去了,没有用,所以我把它拿出来,我将编辑上面的代码。此外,didReceiveData 和 didReceiveResponse 的实现是不完整的,因为在我尝试对数据执行任何操作之前,我一直在等待它们中的任何一个被实际调用。
  • 没关系。 didReceiveData 现在被调用了吗?如果是,您收到的数据只是部分数据块,可能不是有效的 JSON 字符串。您还应该获得didFinishLoadingdidFailWithError 之一。您应该添加这些以帮助调试,也许它因错误而失败并且您还不知道。
  • 在我输入那行代码之前它并没有成功,这就是为什么建议我包含它的原因。无论如何,我上次检查了一个,它仍然没有命中,但后来我包括了你建议的两种方法,现在 didReceiveData 和 didReceiveResponse 都命中了。显然所有方法都是必需的?
  • NSURLConnection 不需要任何方法。我自己对此进行了测试。此外,如果/当您的问题得到解决时,您应该感谢帮助过您、我或其他人的人。特别是如果你想继续得到 SO 上的人的帮助。
  • 显然不同的编程法则适用于我。在过去,由于变量名(rockPile),我的程序无法编译,被注释掉的代码导致我的程序崩溃,现在这个。我非常感谢所有提出建议、提供建议等并且非常愿意给予信任的人。问题是除了添加这两种方法之外,在技术上给出的答案都没有使我的程序工作,所以我应该将哪个标记为正确的“答案”?此外,我没有足够的代表投票赞成任何答案。我愿意接受有关如何给予适当信用的任何建议。
【解决方案4】:

感谢 XJones 的建议。我没有包括didFinishLoadingdidFailWithError 这两种方法,一旦插入我的代码,didReceiveResponsedidReceiveData 都开始起作用。感谢大家的提示、建议和建议,希望这可以帮助其他人。

【讨论】:

  • 不需要NSURLConnection 委托方法。您需要处理 connection:didFinishLoadingconnection:didFailWithError: 才能正确清理,但 NSURLConnection 无论如何都会执行请求。我已经亲自对此进行了测试以验证。我还建议您(通过投票和接受)向 SO、我或其他人,他们花时间帮助您。
  • 嗯,不知道为什么如果没有这两种方法我的就不能工作。只是似乎只适用于我的一长串编程障碍中的另一个。此外,我对每个人都给予信任非常好,我只是不知道将哪个标记为“答案”,因为包括这两种方法是唯一有效的方法。此外,我没有足够的“代表”来投票支持所提供的任何答案。 :(