(in MAC OSX- Xcode) I tried to read file by FTP using NSURLConnection class, it is work fine just if my code in main Application Delegate class (AppDelegate) but if i using it outside (another .h .m files) the connection delegate not called.
Any help!?
here is my code:
-(void)getURL {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"ftp://.... connection string with file"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (connection) {
// Do something
} else {
// Inform the user that the connection failed.
NSLog(#"connection failed");
}
}
Delegates:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"didReceiveResponse");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"connectionDidFinishLoading");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//Getting file data
[receivedData appendData:data];
}
Did you add the delegate <NSURLConnectionDelegate> to the view controller you are trying to use it in ?
for example
#interface ViewController : UIViewController <NSURLConnectionDelegate>
Related
I'm trying to develop a simple OS X application that should do the following:
Read a file to get username and password
Obtain Mac serial number from server
Connect to a remote service to login with username, password and Mac serial number
If the user is authorized to be connected with this service it should run an infinite
Infinite loop should call a service that connect to another service to get news
If there are news it should send a local notification
This application should work without GUI, so I'm using an Xcode command line tool. The application is organized so:
main.m read file with username and password and obtain the Mac serial number
Connection.m should connect to the login service and run the checkNews service
CheckNews.m should connect to the news service and if there are a news should run a class to send local notification
NotificationCenterDelegate.m should simply send the local notification with news inside
My problem is that if I run the app it doesn't connect to the login service, because it doesn't calls the NSConnectionDelegate methods. I searched on the web and I found that the connection should be in the main thread, I tested it by using the following code: NSLog(#"Is%# main thread", ([NSThread isMainThread] ? #"YES" : #" NOT")); and it returned me that the connection is in the main thread, so I don't know why it doesn't run the NSConnectionDelegate methods. If you need I can post the code of my Connection.m class to understand why it doesn't working well. I hope you can help me to fix that issue.
Connection.m
#import "Connection.h"
#import "CheckNews.h"
#interface Connection() {
NSMutableData *responseData;
}
#property(nonatomic,strong)NSString *fakeBundleIdentifier;
#property BOOL installNSBundleHook;
#end
#implementation Connection
- (id)initWithFakeBundle:(NSString *)fakeBundleIdentifier andInstallNSbundleHook:(BOOL)installNSBundleHook {
if (self) {
self.fakeBundleIdentifier = fakeBundleIdentifier;
self.installNSBundleHook = installNSBundleHook;
}
return self;
}
- (id)sendRequestToURL:(NSString *)urlString withMethod:(NSString *)method withUsername:(NSString *)username withPassword:(NSString *)password andSerialNumber:(NSString *)serialNumber {
NSURL *finalURL;
if ([method isEqualToString:#"POST"]) {
finalURL = [NSURL URLWithString:urlString];
} else {
NSLog(#"Metodo no previsto");
}
NSString *post = [NSString stringWithFormat:#"username=%#&password=%#&serialNumber=%#", username, password, serialNumber];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)postData.length];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:finalURL];
[request setHTTPMethod:method];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
if (connection) {
[connection start];
}
return connection;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"%#", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSDictionary *json;
NSError *error;
json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
if ([self loginWithSuccessFromJson:json]) {
[self checkNews];
}
}
- (BOOL)loginWithSuccessFromJson:(NSDictionary *)json {
int success = [[json objectForKey:#"success"]intValue];
if (success == 1) {
return YES;
} else {
return NO;
}
}
- (void) checkNews {
CheckNews *checkNews = [[CheckNews alloc]initWithFakeBundle:self.fakeBundleIdentifier andInstallNSbundleHook:self.installNSBundleHook];
for(;;) {
[checkNews sendRequestToURL:#"" withMethod:#"GET"];
}
}
I'm using
[NSURLConnection connectionWithRequest:req delegate:self];
and then I use
-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
to handle data loading. Everything is ok and working fine but I don't like the beauty of this code )
I wish to use blocks, to make my code looks like this:
[myConnection sendData:data
successBlock:^(void){NSLog(#"success");}
errorBlock:^(NSError * error){NSLog(#"error.description: %#", error.description);}];
is it possible to use NSURLConnection with blocks?
I use this class:
The MyConnection.h
#import <Foundation/Foundation.h>
#interface MyConnection : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
NSURLConnection * internalConnection;
NSMutableData * container;
}
-(id)initWithRequest:(NSURLRequest *)req;
#property (nonatomic,copy)NSURLConnection * internalConnection;
#property (nonatomic,copy)NSURLRequest *request;
#property (nonatomic,copy)void (^completitionBlock) (id obj, NSError * err);
-(void)start;
#end
And the MyConnection.m
#import "MyConnection.h"
static NSMutableArray *sharedConnectionList = nil;
#implementation MyConnection
#synthesize request,completitionBlock,internalConnection;
-(id)initWithRequest:(NSURLRequest *)req {
self = [super init];
if (self) {
[self setRequest:req];
}
return self;
}
-(void)start {
container = [[NSMutableData alloc]init];
internalConnection = [[NSURLConnection alloc]initWithRequest:[self request] delegate:self startImmediately:YES];
if(!sharedConnectionList)
sharedConnectionList = [[NSMutableArray alloc] init];
[sharedConnectionList addObject:self];
}
#pragma mark NSURLConnectionDelegate methods
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[container appendData:data];
}
//If finish, return the data and the error nil
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([self completitionBlock])
[self completitionBlock](container,nil);
[sharedConnectionList removeObject:self];
}
//If fail, return nil and an error
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if([self completitionBlock])
[self completitionBlock](nil,error);
[sharedConnectionList removeObject:self];
}
#end
to use it:
MyConnection * connection = [[MyConnection alloc]initWithRequest:req];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
//It's ok, do domething with the response data (obj)
} else {
//There was an error
}
}];
[connection start];
It's based on the code, The Big Nerd Ranch uses on his book.
I hope it will be helpful.
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(#"%#", response);
NSLog(#"%#", data);
}];
I've done exactly what this official documentation instructed. I created a console project for testing purpose. And then I created a class called RequestSender (see code below) and I made an instance of this class in the main function.
RequestSender.h:
#import <Foundation/Foundation.h>
#interface RequestSender : NSObject <NSURLConnectionDelegate> {
NSMutableData* d;
}
#end
RequestSender.m:
#import "RequestSender.h"
#implementation RequestSender
- (id)init {
self = [super init];
if (self) {
NSString* s = #"http://www.apple.com/";
NSURL* u = [[NSURL alloc] initWithString:s];
NSURLRequest* r = [[NSURLRequest alloc] initWithURL:u];
NSURLConnection* c = [[NSURLConnection alloc] initWithRequest:r delegate:self];
if (c) {
d = [NSMutableData data];
}
return self;
} else {
return nil;
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[d setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[d appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
}
#end
This will no doubt be executed in the main thread and default run loop. However non of the delegation methods are called.
I've done a lot of testing and read many posts but I still don't have a clue.
Please help me. This is driving me mad.
Thanx!
I believe you're missing the part where you start the connection. The connection class offers another method for this, or you could just call it off of your "c" object.
NSURLConnection* c = [[NSURLConnection alloc] initWithRequest:r delegate:self];
if (c) {
d = [NSMutableData data];
[c start];
}
or
NSURLConnection* c = [[NSURLConnection alloc] initWithRequest:r delegate:self startImmediately:YES];
if (c) {
d = [NSMutableData data];
}
Riddle me this: I am using a NSURLConnection on an iPhone Simulator SDK 3.1.2 object to issue multiple sequential (not concurrent) https requests. Everything works fine 95% of the time, but every so often (maybe around 50-100 requests) I get the situation where the delegate method
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
is called after [connection start], but without any call to the delegate method
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
I have reduced the problem down to the source below. From what I understand this breaks the contract of NSURLConnection's defined behaviour. Has anyone else had this problem, and is it a known bug or am I using NSURLConnection wrong?
static BOOL hasSeenResponse = NO;
//Create a NSURLConnection and start it
-(void) begin {
NSURL* url = [NSURL URLWithString#"https://some.domain.com/some/path/?some=query"];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
if ([NSURLConnection canHandleRequest:request]) {
NSURLConnection* connection = [[NSURLConnection connectionWithRequest:request delegate:self] retain];
hasSeenResponse = NO;
[connection start];
}
}
#pragma mark NSURLConnection Delegate Methods
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (!hasSeenResponse) {
NSLog(#"\n\nNo Response Recieved\n");
}
[connection release];
[self begin];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connection release];
[self begin];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
hasSeenResponse = YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
}
I was able to fix the problem by adding the delegate for re-directs which always accepts
-(NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
{
return request;
}
As I understand it, this is the default behavior so I do not know why this solves the problem.
The URL I was sending the request to, did issue a re-direct, but that also does not explain why the HTTP request worked the other ~95% of the time.
I hope this helps someone with a similar problem in the future.
When trying to compile an infinite while loop in xcode iphone view based application, it gives me an error that reads expected identifier or '(' before 'while'. I made it as simple as possible. Sorry about the picture. Code block was not working. If you want to see an image of the code, here is the link. http://www.freeimagehosting.net/uploads/931d5d8788.gif
#import "Lockerz_NotifierViewController.h"
#implementation Lockerz_NotifierViewController
NSMutableData *responseData;
while (1) {
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://amicionline.me"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create a connection
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
// create the datum
responseData=[[NSMutableData data] retain];
} else {
// code this later
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// make it work
NSLog(#"Succeeded! Received %d bytes of data:",[responseData length]);
// release it
[connection release];
[responseData release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
What are you trying to do? You can't write code directly in an #implementation. You must put it inside a method, for example:
-(void)start {
while (1) {
...
}
}