I ran into a problem. I can't image why that happens, probably you guys can.
I've created a UIBarButtonItem in IB and linked it correctly. A set the property and synthesized it. At the beginning I set the btn disabled (viewWillAppear).
Then I try to add an entry to my mysql db:
NSString *URLStr = [NSString stringWithFormat:#"http://www.justfortestingandsoon.com/example.php?entry=%#", myEntry];
URLStr = [URLStr stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSLog(#"URLStr: %#",URLStr);
NSURL *addURL = [NSURL URLWithString:URLStr];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:addURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
urlConnectionSet = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
In it's "didReceiveData..." I check which value gets returned:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSData *myData;
myData = data;
NSString *testString = [[NSString alloc] initWithData:myData encoding:NSASCIIStringEncoding];
NSLog(#"receivedData: %#", testString);
if ([testString isEqualToString:#"ENABLED"]) {
self.notificationBtnDeactivate.enabled = YES;
}
...
I already debugged it. The line self.notificationBtnDeactivate.enabled = YES; gets called but without any noticable changes on the UI.
Any Ideas?
Thanks a lot!
I have two ideas for this:
the buttons are not correctly referenced from IB, add some NSAssert and check against nil
you doing your UI changes on the wrong thread. Try to use performSelectorOnMainThread:withObject:waitUntilDone:
Related
I'm using 2 UICollectionView on one screen and fetching 2 different data sets from my api.
But the problem is that I can't resolve is differentiating the incoming data depending on which view requested.
Here's a code snippet of what I do in the UICollectionView:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *headlineurl = [NSURL URLWithString:#"api1"];
headlinerequest = [NSURLRequest requestWithURL:headlineurl];
[[NSURLConnection alloc] initWithRequest:headlinerequest delegate:self];
NSURL *mostnewsurl = [NSURL URLWithString:#"api2"];
NSURLRequest *mostnewsrequest = [NSURLRequest requestWithURL:mostnewsurl];
[[NSURLConnection alloc] initWithRequest:mostnewsrequest delegate:self];
}
And this is the code from the delegate:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//What should I do here ?
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
//What should I do here ?
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//What should I do here ?
}
Thanks a lot.
Your problem is pretty common when people start using NSUrlConnection delegates,
First thing you're setting the delegate of both views to the same object, which can work, but will need some hackery.
I recommend one of the following solutions:
Solution 1 (uses delegates, more work)
Create a new class, and give give it the NSURlconnection delegate protocol
and call it something like apiFetchDelegate
Then place your delegate methods in there -(void) connectionDidFinishLoading, etc..
Now in your viewDidLoad method, change it to the following:
NSURL *headlineurl = [NSURL URLWithString:#"api1"];
headlinerequest = [NSURLRequest requestWithURL:headlineurl];
//Create a new instance of the delegate
apiFetchDelegate* headlineDelegate = [[apiFetchDelegate alloc] init];
[[NSURLConnection alloc] initWithRequest:headlinerequest delegate:headlineDelegate];
And the second delegate:
NSURL *mostnewsurl = [NSURL URLWithString:#"api2"];
NSURLRequest *mostnewsrequest = [NSURLRequest requestWithURL:mostnewsurl];
//Create second delegate
apiFetchDelegate* mostnewsDelegate = [[apiFetchDelegate alloc] init];
[[NSURLConnection alloc] initWithRequest:mostnewsrequest delegate:mostnewsDelegate];
now as you see, each one will get its own delegate, and data won't be mixed anymore !
Solution 2 (without delegates, less work to do)
This is probably a better solution for your need , I'm not sure why you need delegates for such a simple call, but if you don't , better go with this simple way !.
We will make async calls to avoid freezing the UI while data is being fetched, this will require an NSOperationQueue, here's how it'll work:
In your viewDidLoad method, change the code to this:
//Create your Queue here
NSOperationQueue *apiCallsQueue = [NSOperationQueue alloc] init];
[apiCallsQueue setMaxConcurrentOperations:2];
NSURL *headlineurl = [NSURL URLWithString:#"api1"];
headlinerequest = [NSURLRequest requestWithURL:headlineurl];
[NSURLConnection sendAsynchronousRequest:headlinerequest queue:apiCallsQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//Here is your data for the first view
//
NSLog(#"Data for headline view: %#", [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding]);
}];
And for the second view:
NSURL *mostnewsurl = [NSURL URLWithString:#"api2"];
NSURLRequest *mostnewsrequest = [NSURLRequest requestWithURL:mostnewsurl];
[NSURLConnection sendAsynchronousRequest:mostnewsrequest queue:apiCallsQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//Here is your data, for the second view
//
NSLog(#"Date for latest news: %#", [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding]);
}];
Let me know if this works for you or if you need further assistance.
Hello I am developing one application as currency converter in that, I have URL it will return only one country currency but my module look like if user select one country then I need to display list of currency converter values of more than one country so I need call josn more than one times.
code is as:
responseData = [[NSMutableData data] retain];
ArrData = [NSMutableArray array];
NSString *strURL = [NSString stringWithFormat:#"http://rate-exchange.appspot.com/currency?from=%#&to=%#&q=1",strtablbase,strto];
NSURL *url = [NSURL URLWithString:strURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
results = [responseString JSONValue];
livevalues=[responseString JSONValue];
With above code I am geting one country values but I need pass one strto values differently
Is it possible?
If yes, please give suggestions & help me out from this problem.
Yes you can use NSOperation Queues to call the different URL or if you are using Asihttprequest this Link may be useful for you :)
responseData = [[NSMutableData data] retain];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:#"country1"];
[array addObject:#"country2"];
for (NSString *urlString in array) {
strtablbase = [NSString stringWithFormat:#"%#",urlString];
NSString *strURL = [NSString stringWithFormat:#"http://rate-exchange.appspot.com/currency?from=%#&to=%#&q=1",strtablbase,strto];
NSURL *url = [NSURL URLWithString:strURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
Try this..
Of course it is possible to pass different values. Like you already did you can start connections one after another. If the server belongs to you, I would implement a request which returns me all the rates at a time. It saves the time for sending and receiving request. It really does not matter (for waiting time) if you get 100 bytes or 500 bytes in one request.
Otherwise you need to call many requests. Like said you can call one after another and even 2-3 requests at the same time. You can implement the mechanism your self or you can use NSOperationQueue which is made exactly for many requests by Apple.
For more information https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html
And I want yo point the method (of NSURLConnection)
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
I am doing a registration process with my app where the user enters in a number that I check against my db.. anyway long story short where I pass code into my NSString *startURL have a warning I cannot get rid of, it says
"Expression result unused"
have you ever experienced anything like this and if so how do I fix it?
-(void)startRegConnect:(NSString *)tempRegCode{
//tempRegCode = S.checkString;
NSLog(#"tempRegCode from RegConnection =%#",tempRegCode);
NSString *code = [[NSString alloc] initWithString:tempRegCode];
//urlstart string
NSString *startURL = (#"http://188.162.17.44:8777/ICService/?RegCode=%#",code); //warning here
NSURL *url = [NSURL URLWithString:startURL];
//create a request object with that url
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
//clear out the exisiting connection if there is on
if (connectionInProgress) {
[connectionInProgress cancel];
[connectionInProgress release];
}
//Instantiate the object to hold all incoming data
[cookieData release];
cookieData = [[NSMutableData alloc]init];
//create and initiate the connection - non-blocking
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
You can't just do (#"http://188.162.17.44:8777/ICService/?RegCode=%#",code). Use [NSString stringWithFormat:#"http://188.162.17.44:8777/ICService/?RegCode=%#", tempRegCode].
It's because of the parenthesis. By writing (blabla) it becomes an expression, which you are not using as an expressing, hence the compiler complains.
Change to [NSString stringWithFormat: ...]; and it becomes a method.
I am trying to use initWithContentsOfURL:encoding:error: like this :
NSURL *url = [[NSURL alloc] initWithString:#"http://my_url.com/my_file.xml"];
NSError *error = nil;
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
encoding:NSUTF8StringEncoding
error:&error];
I get a empty my_string variable.
I tried the initWithContentsOfURL: method (which is deprecated in iOS 2.0) and I get the content of my page. But I still need to specify a encoding language.
What's wrong ?
Thanks :)
the encoding of your file is probably not UTF8.
If you don't know the encoding of your file, you could try this method:
- (id)initWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error
you have to pass a pointer to a NSStringEncoding, like you did with error.:
NSURL *url = [[NSURL alloc] initWithString:#"http://my_url.com/my_file.xml"];
NSError *error = nil;
NSStringEncoding encoding;
//NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
// encoding:NSUTF8StringEncoding
// error:&error];
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
after this your encoding is present in the encoding variable. If you are not interested in the used encoding, I guess you could pass NULL as pointer as well.
Why not use a request and connection to get the info back in an NSData object? Something like this:
NSURL *url = [[NSURL alloc] initWithString:#"http://my_url.com/my_file.xml"];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:url];
[request setHTTPMethod:#"GET"];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
[conn start];
if(conn){
// Data Received
responseData = [[NSMutableData alloc] init];
}
and then in your connection:didRecieveData delegate method, put something like this
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
}
and then once the connection is finished loading convert the data to a string:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSString *string = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
}
Not the most straightforward method, but that should get you your XML string. Also if you need to parse the XML once you get it back, you can directly pass the responseData to an NSXMLParser without any conversion. :)
You can modify your webpage by adding header('Content-Type: text/html; charset=UTF-8'); to the top of the code and saving the document as a UTF-8 formated file. It helped me as I had the same problem.
I encounter a problem by following your comment. I would like to download different file at same time with different delegate:
.h:
NSMutableData *fileData;
.m:
NSString *imgfile = [NSString stringWithFormat:#"http://xxxx/01.jpg"];
NSURL *fileURL1 = [NSURL URLWithString:imgfile];
NSString *audiofile = [NSString stringWithFormat:#"http://xxxx/01.mp3"];
NSURL *fileURL2 = [NSURL URLWithString:audiofile];
NSURLRequest *request1 = [NSURLRequest requestWithURL:fileURL1 cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0 ];
NSURLRequest *request2 = [NSURLRequest requestWithURL:fileURL2 cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0 ];
NSArray *connections = [[NSArray alloc] initWithObjects:
[[NSURLConnection alloc] initWithRequest:request1 delegate:self ],
[[NSURLConnection alloc] initWithRequest:request2 delegate:self ],
nil];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
fileData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[fileData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Unable to fetch data");
}
ok, the download process works, but, the file size of jpg and mp3 are incorrect, the only correct thing is the total file size (jpg+mp3), please could you have a look on the code, what is missing?
Another question is, I put the file in a NSMutableArray, my question is, how to check which index of array is the correct file type (jpg and mp3)? because I need to save them to the device folder.
It looks like both your connections write to the same fileData object and all your problems follow from that.
How to deal with multiple connections you can see relevant question asked here on SO, there's also nice blog post containing NSURLConnection subclass that addresses this issue.
Here is what I am doing, I set a counter to identify the file type to save:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSMutableData *dataForConnection = [self dataForConnection:(CustomURLConnection*)connection];
[connection release];
// Do something with the dataForConnection.
downloadCount ++;
// Copy Image Data to ur location using FileManager
//UIImage *img = [UIImage imageWithData:fileData];
NSString *saveDir;
if (downloadCount ==1)
saveDir = [NSString stringWithFormat:#"001.jpg"];
if (downloadCount == 2)
saveDir = [NSString stringWithFormat:#"001.mp3"];
//NSLog(#"saveDir=%#",saveDir);
NSArray * sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString * filePath = [[NSString alloc] initWithFormat: #"%#/%#", [sysPaths objectAtIndex: 0], saveDir];
NSLog(#"filePath=%#",filePath);
if([dataForConnection writeToFile:filePath atomically:YES])
NSLog(#"DONE COPYING");
else
NSLog(#"Write to device error");
//[fileData setLength:0];
if (downloadCount == 2)
{
downloadCount = 0;
play the MP3 and display the image file;
}
}
even I run the app on simulator, the file was download without error reported, but sometimes the file can not be opened, even I tried to open it from the folder, I was told the file was corrupted, I do not understand what was wrong, hope you do understand what I am saying.