I have hobbled together one of my first objects. The goal of the object is to send a text message, which is does. However I'm calling it from the 2nd UIViewController within ViewDidLoad, and its still hanging within the Segue transition. So I know I need to get it asynchronously, but reading some other threads they implied that the proper way to go around it is to make it an "AppDelegate Object", so I would assume I would need to call the object from the AppDelegate, but I'm not really sure about how to go about that as I have not really worked with that in some tutorials I'm doing, and on top of that, is that the correct way to go about using my object?
initializing the object from my view controller
Twilio *twilio = [[Twilio alloc] init];
[twilio sendMessage: self.phoneNumber: [self getRandomNumberBetween:1000 to:9999]];
Header file
#import <Foundation/Foundation.h>
#interface Twilio : NSObject
#property (strong, nonatomic) NSString *TwilioSID;
#property (strong, nonatomic) NSString *TwilioSecret;
#property (strong, nonatomic) NSString *FromNumber;
#property (strong, nonatomic) NSString *ToNumber;
#property (strong, nonatomic) NSString *Message;
-(id)init;
-(id)sendMessage:(NSString *)phoneNumber :(NSString *)message;
#end
Implementation file
#import "Twilio.h"
#implementation Twilio
-(id)init {
self = [super init];
if(self) {
// Twilio Common constants
self.TwilioSID = #"A....3";
self.TwilioSecret = #"e...8";
self.FromNumber = #"5...2";
self.ToNumber = nil;
self.Message = nil;
}
return self;
}
-(id)sendMessage:(NSString *)phoneNumber :(NSString *)message
{
NSLog(#"Sending request.");
self.ToNumber = phoneNumber;
self.Message = message;
// Build request
NSString *urlString = [NSString stringWithFormat:#"https://%#:%##api.twilio.com/2010-04-01/Accounts/%#/SMS/Messages", self.TwilioSID, self.TwilioSecret, self.TwilioSID];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
// Set up the body
NSString *bodyString = [NSString stringWithFormat:#"From=%#&To=%#&Body=%#", self.FromNumber, self.ToNumber, self.Message];
NSData *data = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
NSError *error;
NSURLResponse *response;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// Handle the received data
if (error) {
NSLog(#"Error: %#", error);
} else {
NSString *receivedString = [[NSString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"Request sent. %#", receivedString);
}
return self.Message;
}
#end
Updated
With recommendation below I changed my object implementation like so:
//NSError *error;
//NSURLResponse *response;
//NSData *receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[NSURLConnection sendAsynchronousRequest:request queue:self.queue completionHandler:^(NSURLResponse *response, NSData *data, NSError
*error) {
// Handle the received data
if (error) {
NSLog(#"Error: %#", error);
} else {
NSString *receivedString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Request sent. %#", receivedString);
}
NSLog(#"%#",response);
}];
Use method sendAsynchronousRequest:queue:completionHandler:
See it : https://stackoverflow.com/a/9270711/2828120
Related
I am trying to get the values from a few UITextFields I have added to my storyboard and send them as a JSON string to an API. I can hard code the values for the JSON string and everything works fine. Now I want to retrieve the values from the text fields and insert them in place of the hard coded values. The problem is that when I log the values to the console they are showing up as blank. I am not sure that I have the code correct to get the values from the ViewController to the method that sends the data. I followed several tutorials on how to get the data from the ViewController UITextFields. I connected the text fields to the properties in the ViewController.h file. I am hoping someone can help me figure out what I did wrong, hopefully I provided enough information.
I think the problem may be how I am trying to get the values from these lines of code in the timeMethods.m file:
ViewController *controller = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
NSString *name = controller.name.text;
NSString *type = controller.type.text;
NSString *date = controller.date.text;
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic, retain) IBOutlet UITextField *name;
#property (nonatomic, retain) IBOutlet UITextField *type;
#property (nonatomic, retain) IBOutlet UITextField *date;
#end
ViewController.m
#import "ViewController.h"
#import "timeMethods.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize name;
#synthesize type;
#synthesize date;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)sendRequest:(id)sender {
[[timeMethods alloc] sendRequest];
}
- (IBAction)getRequest:(id)sender {
[[timeMethods alloc] getRequest];
}
#end
timeMethods.m
#import "timeMethods.h"
#implementation timeMethods
- (void)sendRequest {
ViewController *controller = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
NSString *name = controller.name.text;
NSString *type = controller.type.text;
NSString *date = controller.date.text;
NSURL *url = [NSURL URLWithString:#"http://throttle.com/my-rest-api/api/robots"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSDictionary *tmp = [[NSDictionary alloc] initWithObjectsAndKeys:
name, #"name",
type, #"type",
date, #"year",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:tmp options:0 error:&error];
[request setHTTPBody:postData];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[postData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: postData];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
NSString *strData = [[NSString alloc]initWithData:postData encoding:NSUTF8StringEncoding];
NSLog(#"%#", strData);
}
- (void)getRequest {
NSString *serverAddress = #"http://throttle.com/my-rest-api/api/robots";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverAddress]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
[request setHTTPMethod:#"GET"];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
NSString *strData = [[NSString alloc]initWithData:response1 encoding:NSUTF8StringEncoding];
NSLog(#"%#",strData);
}
#end
timeMethods.h
#import <Foundation/Foundation.h>
#interface timeMethods : NSObject
- (void)sendRequest;
- (void)getRequest;
#end
The trouble is that we've just allocated a brand new VC and asked for its UITextField's values here:
ViewController *controller = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
// controller.name is a brand new text field, created in the previous line
NSString *name = controller.name.text; // guaranteed to be #""
Of course this will be an empty text field. It was created in the previous line. Instead, get those values as params to your request from the view controller the user is using...
- (IBAction)sendRequest:(id)sender {
NSString *name = self.name.text;
NSString *type = self.type.text;
NSString *date = self.date.text;
[[timeMethods alloc] sendRequestWithName:name type:type date:date];
}
Naturally, add those parameters to the sendRequest method and remove the local vars.
I write an application for iphone in objective-c and wanna get data from json. but I get null from url, but url is correct and when I pass url to browser I see the json data. this is my IBAction method:
- (IBAction)checkMobileNumber:(id)sender {
NSString *prefix = self.prefixTextField.text;
NSString *number = self.numberTextField.text;
NSString *url =[NSString stringWithFormat:#"http://data.e-gov.az/api/v1/IEGOVService.svc/CheckMobileProvider/%#/%#", prefix, number];
NSURL *jsonURL = [NSURL URLWithString:url];
#try {
[[[NSURLSession sharedSession] dataTaskWithURL:jsonURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString* rawJSON = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSError *err;
self.checkMobile = [[CheckMobileProviderModel alloc] initWithString:rawJSON error:nil];
if (err) {
NSLog(#"Unable to initialize PublicPhotosModel, %#", err.localizedDescription);
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%#", self.checkMobile.response);
//NSLog(#"%#", self.checkMobile.fault[#"faultString"]);
});
}] resume];
}
#catch (NSException * e) {
NSLog(#"Exception: %#", e);
}
}
what is wrong here? any help?
EDIT:
my CheckMobileProviderModel.h
#import "JSONModel.h"
#import "FaultModel.h"
#protocol FaultModel
#end
#interface CheckMobileProviderModel : JSONModel
#property (strong, nonatomic) NSString *response;
#property (strong, nonatomic) NSArray<FaultModel, Optional>* fault;
#end
and FaultModel.h
#import "JSONModel.h"
#interface FaultModel : JSONModel
#property (strong, nonatomic) NSString* faultCode;
#property (strong, nonatomic) NSString* faultString;
#end
Do not convert the JSON to a string:
NSString* rawJSON = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
convert it is an object, in this case a NSDictionary
NSError = *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (dict) {
NSLog(#"dict: %#", dict);
}
else {
NSLog(#"error: %#", error);
}
The JSON in the comment nicely formatted:
{
"fault":{
"faultCode":1,
"faultString":"Məlumat yoxdur"
},
response":"Cari nömrə üçün mobil daşınma xidmətindən istifadə edilməmişdir"
}
Translated:
{
"fault":{
"faultCode":1,
"faultString":"there is no information"
},
response":"The current number is not used for a mobile carriage service"
}
I've been really confused to solve this problem .
I want get response from https Xcode.
this is the URL -> https://staping.faboo.co.id/ ( The url is not real )
Response from that url is XML format like this :
<response>
<GeneralResponse>
<status>2</status>
<desc>Data Not Found</desc>
</GeneralResponse>
</response>
My code fabooViewController.h is like this :
#import <UIKit/UIKit.h>
#interface FabooViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *passwordField;
#property (weak, nonatomic) IBOutlet UITextField *emailField;
#property (weak, nonatomic) IBOutlet UIButton *buttonLogin;
#property (weak, nonatomic) NSArray *trustedHosts;
#end
My code fabooViewController.m is like this :
- (IBAction)loginAction:(id)sender {
NSString *email = _emailField.text;
NSString *password = _passwordField.text;
NSString *url_string = [NSString stringWithFormat: #"https://staping.faboo.co.id/email=%#&pass=%#",email,password];
NSLog(#"url : %#",url_string);
NSURL *URL = [NSURL URLWithString:url_string];
_trustedHosts = [NSArray arrayWithObjects:#"https://staping.faboo.co.id",nil];
NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:URL];
NSError *error = nil;
NSData *data = [ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];
if (error)
{
NSLog(#"error %#", [error localizedDescription]);
}
else
{
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
NSLog(#"Result %#", result);
}
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(#"host : %#",_trustedHosts);
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
if ([_trustedHosts containsObject:challenge.protectionSpace.host])
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
and the error is:
FabooUniversalApp[1570:4903] NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)
2014-06-10 13:35:19.541 FabooUniversalApp[1570:60b] error The certificate for this server is invalid. You might be connecting to a server that is pretending to be “staping.faboo.co.id” which could put your confidential information at risk.
what should I do?
Edited:
i use this link How to use NSURLConnection to connect with SSL for an untrusted cert? for my reference
SOLVED
in my file.m i implemented NSURLRequest
#interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
#end
and i use this code to get result from https :
NSString *url_string = #"your url";
NSLog(#"url : %#",url_string);
NSURL *URL = [NSURL URLWithString:url_string];
NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:URL];
NSError *error = nil;
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
NSURLResponse *response;
NSData *data = [ NSURLConnection sendSynchronousRequest: urlRequest returningResponse:&response error: &error ];
if (error)
{
NSLog(#"error %#", [error localizedDescription]);
}
else
{
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
NSLog(#"Result %#", result);
NSData *xmlData = [result dataUsingEncoding:NSASCIIStringEncoding];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];
[xmlParser setDelegate:self];
[xmlParser parse];
}
I'm trying to return String from this method i have two class
first one is for UI and it have two input text user and pass and also i have submit button , another one only doing the following method .
I'm trying to return string from the other class to this class and show the string in alert .
#import "LoginPage.h"
#implementation LoginPage
-(NSString *)responsData:(NSString *)loginUrl input1:(NSString *)username input2:(NSString *)password
{
NSString *urlAsString = loginUrl;
NSString*test;
inUsername = username;
inPassword = password;
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"POST"];
// Setting Username and password
NSString *body = [NSString stringWithFormat:#"sended=yes&username=%#&password=%#",username,password];
[urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error)
{
if ([data length] >0 && error == nil){ NSString *html =
[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
// NSLog(#"%#", html);
self.lastValue = [NSString stringWithFormat:#"%#",html];
}
else if ([data length] == 0 && error == nil){
//NSLog(#"Nothing was downloaded.");
self.lastValue = [NSString stringWithFormat:#"No thing was downloaded"];
}
else if (error != nil){
// NSLog(#"Error happened = %#", error);
self.lastValue = [NSString stringWithFormat:#"%#",error];
} }];
NSLog(#"%#",self.lastValue);
return self.lastValue;
}
// Do any additional setup after loading the view, typically from a nib.
#end
i want to use this function in another view ( already i include the header of this file ) but i can't , can any one solve this >
another view
- (IBAction)submit:(id)sender {
LoginPage * login = [[LoginPage alloc]init];
NSString * dataRe;
dataRe = [login responsData:#"http://fahads-macbook-pro.local/ios/post.php" input1:#"admin" input2:#"1234"];
NSLog(#"%#",login.lastValue);
if (dataRe != nil) {
UIAlertView * alert =[[UIAlertView alloc]
initWithTitle:#"Hello Fahad"
message:[NSString stringWithFormat:#"%#",dataRe] delegate:self cancelButtonTitle:#"Okay ! " otherButtonTitles:nil, nil];
[alert show];
}
}
Thank you again
When you call the function on the other view, it send an asynch request to the web.
So when you do:
return self.lastValue;
lastValue is still empty or with the previous value because the competionHandler need still to be called. Code of the completionHandler, is just a peace of code passed to the function, that will be called at right moment. So the function arrive to the end where is your return.
When instead the completion handler block is called (because the request has produced a response), you assign the value:
self.lastValue = [NSString stringWithFormat:#"%#",html];
Now lastValue is right.
So your function shouldn't return an NSString, but should return void.
To pass the string to the other controller, you should use the delegation pattern.
This is a very quickly example
SecondViewController.h
#protocol SecondViewControllerDelegate <NSObject>
- (void)lastValueDidUpdate:(NSString *)lastValue;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id<SecondViewControllerDelegate>delegate;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
-(NSString *)responsData:(NSString *)loginUrl input1:(NSString *)username input2:(NSString *)password
{
NSString *urlAsString = loginUrl;
NSString*test;
inUsername = username;
inPassword = password;
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"POST"];
// Setting Username and password
NSString *body = [NSString stringWithFormat:#"sended=yes&username=%#&password=%#",username,password];
[urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
__weak typeof (self) weakSelf = self;
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error)
{
if ([data length] >0 && error == nil){ NSString *html =
[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
// NSLog(#"%#", html);
weakSelf.lastValue = [NSString stringWithFormat:#"%#",html];
}
else if ([data length] == 0 && error == nil){
//NSLog(#"Nothing was downloaded.");
weakSelf.lastValue = [NSString stringWithFormat:#"No thing was downloaded"];
}
else if (error != nil){
// NSLog(#"Error happened = %#", error);
weakSelf.lastValue = [NSString stringWithFormat:#"%#",error];
}
[weakSelf.delegate lastValueDidUpdate:weakSelf.lastValue];
}];
}
#end
FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController <SecondViewControllerDelegate>
#property (strong, nonatomic) SecondViewController *secondViewController;
#end
FirstViewController.m
#import "FirstViewController.h"
#implementation FirstViewController
- (void)viewDidLoad {
//your code
[_secondViewController setDelegate:self];
//your code
}
//your code
#end
Note that i use a weak reference to self because otherwise you can create retain cycle.
Define a method in your first class i.e. UI class like:
- (void)callFromBlock:(NSString*)stringFromResponse
{
if (stringFromResponse != nil) {
UIAlertView * alert =[[UIAlertView alloc]
initWithTitle:#"Hello Fahad"
message:[NSString stringWithFormat:#"%#",stringFromResponse] delegate:self cancelButtonTitle:#"Okay ! " otherButtonTitles:nil, nil];
[alert show];
}
}
and the submit method should look like:
- (IBAction)submit:(id)sender {
LoginPage * login = [[LoginPage alloc]init];
NSString * dataRe;
dataRe = [login responsData:#"http://fahads-macbook-pro.local/ios/post.php" input1:#"admin" input2:#"1234"];
}
Now instead of return statement in the block, call the callFromBlock method from the block when you get the response and pass the string to this method you were trying to return.
Hope it helps.
I am using this function to upload an image to a server using JSON. In order to do so, I first convert the image to NSData and then to NSString using Base64. The method works fine when the image is not very large but when I try to upload a 2Mb image, it crashes.
The problem is that the server doesn't receive my image even though the didReceiveResponse method is called as well as the didReceiveData which returns (null). At first I thought it was a time out issue but even setting it to 1000.0 it still doesn't work. Any idea? Thanks for your time!
Here's my current code:
- (void) imageRequest {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://www.myurltouploadimage.com/services/v1/upload.json"]];
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [NSString stringWithFormat:#"%#/design%i.png",docDir, designNum];
NSLog(#"%#",path);
NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]);
[Base64 initialize];
NSString *imageString = [Base64 encode:imageData];
NSArray *keys = [NSArray arrayWithObjects:#"design",nil];
NSArray *objects = [NSArray arrayWithObjects:imageString,nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d",[jsonData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"Image uploaded");
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"didReceiveResponse");
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"%#",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}
I finally decided to upload the Base64 image splitting it into smaller substrings. In order to do so, and as I needed many NSURLConnections, I created a subclass named TagConnection which gives a tag for each connection so that there's no possible confusion between them.
Then I created a TagConnection property in MyViewController with the purpose of accessing it from any function. As you can see, there's the -startAsyncLoad:withTag: function that allocs and inits the TagConnection and the -connection:didReceiveData: one which deletes it when I receive a response from the server.
Referring to the -uploadImage function, firstly, it converts the image into string and then splits it and put the chunks inside the JSON request. It is called until the variable offset is larger than the string length which means that all the chunks have been uploaded.
You can also prove that every chunk has been successfully uploaded by checking the server response every time and only calling the -uploadImage function when it returns success.
I hope this has been a useful answer. Thanks.
TagConnection.h
#interface TagConnection : NSURLConnection {
NSString *tag;
}
#property (strong, nonatomic) NSString *tag;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag;
#end
TagConnection.m
#import "TagConnection.h"
#implementation TagConnection
#synthesize tag;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag {
self = [super initWithRequest:request delegate:delegate startImmediately:startImmediately];
if (self) {
self.tag = tag;
}
return self;
}
- (void)dealloc {
[tag release];
[super dealloc];
}
#end
MyViewController.h
#import "TagConnection.h"
#interface MyViewController : UIViewController
#property (strong, nonatomic) TagConnection *conn;
MyViewController.m
#import "MyViewController.h"
#interface MyViewController ()
#end
#synthesize conn;
bool stopSending = NO;
int chunkNum = 1;
int offset = 0;
- (IBAction) uploadImageButton:(id)sender {
[self uploadImage];
}
- (void) startAsyncLoad:(NSMutableURLRequest *)request withTag:(NSString *)tag {
self.conn = [[[TagConnection alloc] initWithRequest:request delegate:self startImmediately:YES tag:tag] autorelease];
}
- (void) uploadImage {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://www.mywebpage.com/upload.json"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1000.0];
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [NSString stringWithFormat:#"%#/design%i.png", docDir, designNum];
NSLog(#"%#",path);
NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]);
[Base64 initialize];
NSString *imageString = [Base64 encode:imageData];
NSUInteger length = [imageString length];
NSUInteger chunkSize = 1000;
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSString *chunk = [imageString substringWithRange:NSMakeRange(offset, thisChunkSize)];
offset += thisChunkSize;
NSArray *keys = [NSArray arrayWithObjects:#"design",#"design_id",#"fragment_id",nil];
NSArray *objects = [NSArray arrayWithObjects:chunk,#"design_id",[NSString stringWithFormat:#"%i", chunkNum],nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d",[jsonData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
[self startAsyncLoad:request withTag:[NSString stringWithFormat:#"tag%i",chunkNum]];
if (offset > length) {
stopSending = YES;
}
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSError *error;
NSArray *responseData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (!responseData) {
NSLog(#"Error parsing JSON: %#", error);
} else {
if (stopSending == NO) {
chunkNum++;
[self.conn cancel];
self.conn = nil;
[self uploadImage];
} else {
NSLog(#"---------Image sent---------");
}
}
}
#end
Please don't think this is the last option, this is just my observation.
I think you should send that NSData in chunks instead of complete Data.
I have seen such methodology in YouTube Video Uploading case.They send the Large set of NSData (NSData of Video File) in Chunks of many NSData.
They uses the Same Methodology for uploading the large data.
So should do google about the Youtube data Uploading API.And you should search out that method , YouTube Uploader Uses.
I hope it may help you .