I've got to load a refreshtoken for an API everytime the user opens the app.
In my appDelegate.m I'm calling this code everytime the app opens:
if(success){ //if the url was successfully retrieved
_webview=[[UIWebView alloc]init];
NSString *url=success;
NSURL *nsurl=[NSURL URLWithString:url];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[_webview loadRequest:nsrequest];
NSLog(#"refreshtoken: %#", success); // logs "website.com/token"
}
somehow, however, the webview doesn't load the request. In my appDelegate.h I'm creating this property: #property (nonatomic) UIWebView *webview;
How come that this does not work?
update
As in the answer pointed out, I'm now using
`[NSURLConnection sendAsynchronousRequest:nsrequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error){
NSLog(#"%#",[error localizedDescription]);
}
else{
NSLog(#"data: %#", data);
}
}];
`
instead of [_webview loadRequest:nsrequest];
When logging the error however, I'm getting this response:
unsupported URL
This is the url that I'm passing:
unicmedia.nl/redacted/startredacted.php?userid=redacted&refreshtoken=redacted
update#1
url didn't start with http:// that's why the error occured.
Is the idea to do an http request? In the app delegate, this is better done with an NSURLConnection. The web view being created in the posted code is getting instantly freed (under ARC) as it goes out of scope. If it's a requirement that you use a web view, keep a strong property to it in your app delegate.
NSURLRequest *request = // form your request
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// check error, handle result
}];
Related
I have a nested loop of sending the request.
-(void) download
{
for(NSString *id in array)
{
//init with request and start the connection
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request deletegate:self];
[conn start];
}
}
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data
{
//enter here secondly
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
//enter here last, after finish the for loop
//my intention is use the downloaded data to do something before sending a new request.
}
The problem is that I want to enter "-(void) connectionDidFinishLoading:(NSURLConnection *) connection" first before send the request again in the for loop.
But currently it will finish the for loop and sent all the request before enter to "-(void) connectionDidFinishLoading:(NSURLConnection *) connection".
You Should Try This NSURLConnection is deprecated in iOS9
for (NSString *URL in URLArray) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// check error and/or handle response here
}];
[task resume];
}
and use dispatch_group_t group = dispatch_group_create();
add line to for loop dispatch_group_enter(group); will call
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// Request Finish
});
for your goal
In your case you need to try block function because as per your requirement you want response of the first connection for another request.
for(NSString* url in array)
{
// Generate a NSURLRequest object from the address of the API.
NSURL *url = [NSURL URLWithString:urlLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// Send the request asynchronous request using block!
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"Error in updateInfoFromServer: %# %#", error, [error localizedDescription]);
} else if (!response) {
NSLog(#"Could not reach server!");
} else if (!data) {
NSLog(#"Server did not return any data!");
} else {
[self doStuffWithData:data];
}
}];
}
URL loading is not a synchronous operation (or at least should never be done synchronously), because it can take up to 90 seconds just for a DNS lookup failure, and almost infinitely long if the server keeps dribbling out data. If you block the main thread for even a fraction of that amount of time, iOS will kill your app.
Instead of scheduling the requests in a loop and waiting for them to finish, you need to schedule the first request (and only the first request). Then, in your connectionDidFinishLoading: method (and maybe your connection:DidFailWithError: method), schedule the next request.
With that said, unless you still need to support iOS 6/10.8 and earlier, you should probably be using NSURLSession. (The same general advice applies; the delegate method names are changed to protect the guilty.)
can i show an instagram photo on my UIImageView?
I was looking for media id and other options, but i can't find the format and the way to show this image for example:
https://www.instagram.com/p/9W-K0wtq3v/
You can get direct link to image using http://api.instagram.com/oembed?url= . After that, downloading the image from that URL & displaying it in UIImageView is fairly simple. I have edited my answer to this one as it works without integrating Instagram API or parsing the web page for URL to file.
Add the following to methods to your View Controller. I have added explanation in comments.
- (void)getDirectURLToLink:(NSString *)urlStr completionBlock:(void (^)(BOOL succeeded, NSString *imageLink))completionBlock
{
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
{
//Convert data to dictionary as it is JSON. You can view json response for your url at http://paste.ubuntu.com/14437288/
NSError *error1;
NSMutableDictionary * innerJson = [NSJSONSerialization
JSONObjectWithData:data options:kNilOptions error:&error1
];
//Send the direct url to block
completionBlock(YES,[innerJson objectForKey:#"thumbnail_url"]);
} else{
//request failed
completionBlock(NO,nil);
}
}];
}
- (void)downloadImageWithURL:(NSString *)urlStr completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
{
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
{
//cnvert data to uiimage
UIImage *image = [[UIImage alloc] initWithData:data];
completionBlock(YES,image);
} else{
//download failed
completionBlock(NO,nil);
}
}];
}
(But since sendAsynchronusRequest is deprecated in iOS 9.0, you should use [NSURLSession dataTaskWithURL])
Now you have set up the web request part of the file. To utilize these services, Add following method to your Viewcontroller:
-(void) getImageForPostURL: (NSString *)postURL
{
NSString *baseURL = #"http://api.instagram.com/oembed?url=";
NSString *directLinkRequestURL = [NSString stringWithFormat:#"%#%#",baseURL,postURL];
//Request Direct URL to file from your post url
[self getDirectURLToLink:directLinkRequestURL completionBlock:^(BOOL succeeded, NSString *imgDirectURL) {
if (succeeded) {
//Direct link retrieved
//Get image
[self downloadImageWithURL:imgDirectURL completionBlock:^(BOOL succeeded, UIImage *image) {
if (succeeded) {
// change the image where you want, it has been downloaded
_imgView.image = image;
}
}];
}
else
{
//Error
//Link could not be retrieved
}
}];
}
All this work is not for vain. Now, You are all set to go. All you need is a URL to instagram post and you will be able to download your image just by calling this one line:
[self getImageForPostURL:#"https://www.instagram.com/p/9W-K0wtq3v/"]; //Give your post url as parameter here
I think: it will have two ways to achieve your goal
*First: parse link web Instagram. If you view source your link give: you will find direct link to image:
https://igcdn-photos-b-a.akamaihd.net/hphotos-ak-xfp1/t51.2885-15/e35/10729433_781480525295113_239273684_n.jpg
So you can parse web and find:
<meta property="og:image" content="
for direct link.
Second: You can reference here:
https://instagram.com/developer/endpoints/media/
You enroll developer instagram and learn how to use Instagram API end points.
How can I call a webpage (access it without showing it on the display) within an iOS app? I want to be able to have an iOS app, that when opened, will in the background load a webpage, that will execute a shell script.
I think you should use a NSURLConnection with your URL and ignore the data received.
Take a look to Apple Documentation:
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData dataWithCapacity: 0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (!theConnection) {
// Release the receivedData object.
receivedData = nil;
// Inform the user that the connection failed.
}
https://developer.apple.com/library/prerelease/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
See the UIWebView docs:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebView_Class/#//apple_ref/occ/instm/UIWebView/loadRequest:
The request will load even if you dont attach the webview to the view hierarcy. Then implement this method in the UIWebViewDelegate protocol:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIWebViewDelegate/webViewDidFinishLoad:
When loaded, you can inject any (java)script you like with:
stringByEvaluatingJavaScriptFromString:
for a HTTP GET just do:
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"YOUR_YOUR_STRING"]]
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//handle it if you like
}];
I'm trying to load a picture from Facebook's source (a picture I've uploaded through my app and saved it's source).
I'm using AFNetworking to handle all my networking needs but when i'm trying to load a picture from:
http://fbcdn-sphotos-e-a.akamaihd.net/hphotos-ak-xfa1/v/t1.0-9/s720x720/10314676_10152739718934904_452946709678730535_n.jpg?oh=7e73d62e46c33e541e559e07e12bf275&oe=54B7E8CB&gda=1421866048_e364ab835ea15826e7ff28c8382ac085
(which opens in the browser, or in a regular http get request i'm setting in a http generator) but from the AFNetworking it always get a bad request (403) error..
I think that because the response from the server will be image\jpeg and i've ready that by default it doesn't work with AFNetworking..
How can i add it to the serialzer? or should i just write a new http request ?
imageView.imageResponseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"image/jpeg", #"image/jpg"];
I've ended up using:
-(void) loadPictureFromUrl:(NSString*)urlString {
NSURL* url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
[_httpRequestDelegate httpResponseReceived:nil responsedData:[[UIImage alloc] initWithData:data]];
else
[_httpRequestDelegate httpRequestReturnedError:nil withError:error];
}];
}
instead of fighting with AfNetworking - which is usually awesome but has an issue with what i'm trying to do
I'm fairly new to iOS development and I've been stuck on this bug for a while. I'm making a simple app the uses a web service. Right now I currently have two view controllers. A login view controller (with its NIB file) and a main view controller (with its NIB file). When I created the app I chose an empty application so I don't have a storyboard. Instead I'm using UINavigationController. When I run my code I get the following error after entering my username and password and pressing submit in the login view:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called from the main thread.'
This is the code I have for my submit button:
-(IBAction)logIn:(id)sender{
UIApplication *application = [UIApplication sharedApplication];
application.networkActivityIndicatorVisible = YES;
[_loginNetworkingContorller checkCredentialsWithUsername:self.username.text withPassword:self.password.text completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error){
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
NSLog(#"SUCESS");
NSDictionary *credentials = #{self.username.text: self.password.text};
[KeychainUserPass save:#"MY APP" data:credentials];
UIViewController *mainView = [[RDMainViewController alloc] initWithNibName:#"RDMainViewController" bundle:nil];
[self.navigationController pushViewController:mainView animated:YES];
}
else{
NSLog(#"ERROR");
}
}
else{
NSLog(#"ERROR");
}
}];
}
And here is the code for the following function
[_loginNetworkingContorller checkCredentialsWithUsername:self.username.text withPassword:self.password.text completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
-(void)checkCredentialsWithUsername:(NSString *)username withPassword:(NSString *)password completionHandler:(void (^)(NSData *data,NSURLResponse *response, NSError *error))myCompletion
{
NSString *requestString = #"SOME WEBSITE";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSData *userPasswordData = [[NSString stringWithFormat:#"%#:%#", username, password] dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:#"Basic %#", base64EncodedCredential];
NSURLSessionConfiguration *sessionConfig=[NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders=#{#"Authorization":authString};
self.session=[NSURLSession sessionWithConfiguration:sessionConfig];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
myCompletion(data, response, error);
}];
[dataTask resume];
}
I'm a stuck right now and am not really sure what the issue is especially since I don't do anything with the keyboard. I have a feeling there is an issue with my blocks but I'm not exactly sure what the issue is. Any help would be greatly appreciated.
Hey I had this same issue after I received my response from my web call. I was able to solve it be doing the following:
//do something with response
dispatch_async(dispatch_get_main_queue()) { () -> Void in
// continue with program by calling next step on main thread
}
I think if you push to the next view controller iOS attempts to do it on not the main thread, causing the error, but I'm not 100% is that is accurate