I have a special URL that returns an image in a browser. I'd like to put this special image into a UIImage object. However, in my code sample below, it seems that the data returned is not an image.
The browser seems to know about the image, how can I get to the image?
Yes, I need get this image via the proxify proxy server to solve an issue we have.
Here is the sample code.
-(UIImage*)retrieveMap
{
NSString* proxifiedGoogleMapURL = #"http://proxify.com/p/011010A1000100/687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170732f6170692f7374617469636d61703f63656e7465723d34312e3031343130312c2d3130342e393738333333267a6f6f6d3d362673697a653d35303678353036267363616c653d32266d6170747970653d726f61647326666f726d61743d706e672673656e736f723d66616c7365";
NSURLRequest * firstRequest = [NSURLRequest requestWithURL:[NSURL URLWithString: proxifiedGoogleMapURL]];
NSURLResponse * firstResponse = nil;
NSError * firstError = nil;
NSData* firstData = [NSURLConnection sendSynchronousRequest:firstRequest returningResponse:&firstResponse error:&firstError];
UIImage* dataAsImage = [UIImage imageWithData:firstData];
if(firstError != nil || dataAsImage == nil)
{
NSLog(#"Failed in retrieving the map");
}
else
{
NSLog(#"Succeeded in retrieving the map");
}
return dataAsImage;
}
I've spotted a few problems:
You should test firstError != nil before you try to convert to an UIImage. Testing it after kind of makes it useless.
I've tried to access that URL you posted and I got an error saying it is available only to users logged in. In the browser it might work for you since you are probably logged in, but the iphone is not and you get that HTML from proxify
To see the response you get, before creating the image convert it to NSString and display it to the console:
NSLog(#"Response from server: %#", [[NSString alloc] initWithData:firstData encoding:NSUTF8StringEncoding]
Related
AWSStaticCredentialsProvider *credentialsProvider = [[AWSStaticCredentialsProvider alloc] initWithAccessKey:#"AKIA..........." secretKey:#"6FuqRt................."];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionEUWest2 credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
self.transferManager = [AWSS3TransferManager defaultS3TransferManager];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"qr" ofType:#"jpeg"];
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = #"my-flologic-bucket";
uploadRequest.key = #"monday.jpeg";
uploadRequest.body = [NSURL fileURLWithPath:filePath];
[[self.transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task)
{
if (task.error)
{
NSLog(#"Error: %#", task.error);
}
else {
NSLog(#"The file uploaded successfully.");
}
return nil;
}];
ERROR:
Bucket=my-flologic-bucket,
Endpoint=my-flologic-bucket.s3-us-west-2.amazonaws.com, Message=The
bucket you are attempting to access must be addressed using the
specified endpoint. Please send all future requests to this endpoint.,
Code=PermanentRedirect, RequestId=E7471ACE4D6049F8}
As per the regions and endpoints document from AWS Regions and Endpoints, below region endpoints are valid for S3 us-west-2:
s3.us-west-2.amazonaws.com
s3-us-west-2.amazonaws.com
s3.dualstack.us-west-2.amazonaws.com
Can you try using https://<bucket-name>.s3.us-west-2.amazonaws.com instead of s3-us-west-2.amazonaws.com. I understand s3-us-west-2.amazonaws.com is also valid, but I've always used the previous one without any issues.
-- a question about how to make an object that is saved to the documents directory persist on the drive and be recoverable after the iDevice is rebooted.
Here's my problem. I make a data object with NSCoding and fill it with data. I write it to the documentsDirectory each time the data in the object are updated. I stop the app and start the app again, and my data object persists, with all of its data. But if I reboot the iPhone the code I wrote to recover and read the data object fails.
The code I wrote originally used only a NSString for the file path. It worked well under ios7 but it fails under ios8.
Reading up on things, I found this clue from the Apple documentation:
"Important: Although they are safe to use while your app is running, file reference URLs are not safe to store and reuse between launches of your app because a file’s ID may change if the system is rebooted. If you want to store the location of a file persistently between launches of your app, create a bookmark as described in Locating Files Using Bookmarks."
So I rewrote my ios7 file open and file close methods so they no longer use strings or urls but get their strings and urls from a bookmark that is saved using NSUserDefaults. Same problem: everything works fine so long as I do not power off the phone, but all is lost once I do. I am not able to solve this.
Here is my current series of steps. First I either determine (or if it already exists in NSUsrDefaults, I recover) the absolute path to the documentsDirectory, using a bookmark:
+ (NSString*) getGeoModelAbsolutePath
{
NSString *path;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSURL *documentsDirectoryBookmarkURL;
NSData* documentsDirectoryBookmark = [userDefaults objectForKey:#"documentDirectoryBookmark"];
if(documentsDirectoryBookmark == nil)
{
documentsDirectoryBookmarkURL = [self getDocumentsDirectoryURL];
documentsDirectoryBookmark = [self bookmarkForURL:documentsDirectoryBookmarkURL];
}
documentsDirectoryBookmarkURL = [self urlForBookmark:documentsDirectoryBookmark];
path = documentsDirectoryBookmarkURL.path;
path = [path stringByAppendingString:#"/Model.mod"];
return path;
}
using methods modified from my ios7 code (which used only the getDocumentsDirectory method):
+ (NSString *)getDocumentsDirectory
{
NSURL *directory = [self getDocumentsDirectoryURL];
NSString * documentsDirectory = directory.path;
return documentsDirectory;
}
And
+ (NSURL *)getDocumentsDirectoryURL
{
NSURL *directory = [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask]
lastObject];
return directory;
}
And
+ (NSData*)bookmarkForURL:(NSURL*)url {
NSError* theError = nil;
NSData* bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&theError];
if (theError || (bookmark == nil)) {
// Handle any errors.
return nil;
}
return bookmark;
}
So now I have a NSString path with the model filename that I can use to get to the GeoModel
- (GeoModel*) openGeoModel
{
GeoModel *geoModel;
NSString* documentsDirectoryGeoModel =[FileManager getGeoModelAbsolutePath];
if([FileManager fileExistsAtAbsolutePath:documentsDirectoryGeoModel])
{
NSData* data = [NSData dataWithContentsOfFile: documentsDirectoryGeoModel]; //]documentsDirectoryGeoModel];
geoModel = [NSKeyedUnarchiver unarchiveObjectWithData: data];
NSString *unarchivedGeoModelVersion = geoModel.geoModel_VersionID;
if(![unarchivedGeoModelVersion isEqual: currentGeoModelVersion])
{
[FileManager deleteFile:documentsDirectoryGeoModel];
geoModel = [GeoModel geoModelInit];
[Utilities setGeoProjectCounter:0];
}
}
else
{
geoModel = [GeoModel geoModelInit];
}
[FileManager saveGeoModel];
return geoModel;
}
Which I then can save to the documentsDirectory as follows:
+ (BOOL)saveGeoModel
{
NSError *error = nil;
NSString *path = [self getGeoModelAbsolutePath];
[NSKeyedArchiver archiveRootObject:appDelegate.currentGeoModel toFile:path];
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: appDelegate.currentGeoModel];
BOOL success = [encodedData writeToFile: path options:NSDataWritingAtomic error:&error];
return success;
}
Which is always successful -- but is persistent only if I do not turn off the device! I am not making any progress with this: Any help would be much appreciated!
Thanks in advance
Tim Redfield
There. I think it is answered -- unless someone else has a comment on how to improve the above listings, they DO work as they ought to!
I trying to implement Load image asynchronously.
NSURL *url = [NSURL URLWithString:_posterImg];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage *getImg = [[UIImage alloc] initWithData:data];
// do whatever you want with image
}
}];
But when i put this code, getImg will get warning "Unused Variable". i had check "response", "data" and "error", it all look fine but the getImg is NIL. is that i had write any thing wrong? thanks.
The affected variable is response. Although you use data and error, response is only declared as a parameter but nowhere used in your completion handler!
NSURL *url = [NSURL URLWithString:_posterImg];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
NSString *errorMsg = nil;
UIImage *getImg = nil;
if (!error){
getImg = [[UIImage alloc] initWithData:data];
}
else
{
errorMsg = [NSString stringWithFormat:#"Failed to load image. Error Message: %#", [error localizedString]];
}
[self handleImageRequestWithResponse:response image:getImg andErrorMessage:errorMsg];
}];
// Image hasn't load yet here since the request is asynchronously!
//if(getImg != nil && errorMsg == nil)
// NSLog(#"Image is available!");
//else
// NSLog(#"Loading the image asynchronously failed! %#", errorMsg);
// In addition now provide the following method.
- (void) handleImageRequestWithResponse:(NSURLResponse*)response image:(UIImage*)img andErrorMessage:(NSString*)err
{
if(img!= nil && err == nil)
NSLog(#"Image is available!");
else
NSLog(#"Loading the image asynchronously failed! %#", err);
// Handle image
};
EDIT: My bad! Since the code executes asynchronously getImg was of course nil when you checked as before
EDIT:
Using NSData dataWithContentsOfURL is synchronous,i.e. if executed on the main thread your application is blocked.
See this official documentation: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html#//apple_ref/occ/clm/NSData/dataWithContentsOfURL:
Most important:
Important: Do not use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.
Going for a completionHandler and a handler method called after the requested raw data has been handled/prepared is better for your performance and does not violate the official recommendation!
I trying to record a video and I'm getting the error like
Cannot record to URL <#file url> because it is not a file URL.
I define the destination url as follows:
NSString *Path = [[NSString alloc] init];
Path = #"/Users/me/Documents/My fols/recording_try/newMovie.mov";
NSURL *dest = [[NSURL alloc] initWithString:[Path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
Then after creating the session, input and output objects. I tried recording like this.
mMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init] ;
[mSession addOutput:mMovieFileOutput];
[mMovieFileOutput startRecordingToOutputFileURL:dest recordingDelegate:self];
I have started running the session, tried using begin and comitconfiguration, etc. But every time I run I get an error like:
[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] - Cannot record to URL /Users/me/Documents/My%20fols/recording_try/newMovie.mov because it is not a file URL.
I don't know where I'm going wrong... Could someone please help???
Thanks in Advance...
Just change your NSURL configuration to conform to file URL type
Something like this:
NSURL *dest = [[NSURL alloc] initFileURLWithPath:<#(NSString *)#>]
Try something like this:
// variable names should start with lower case letters
// also, let's do as much as we can with auto-released objects
// so we don't have to worry about leaking (if we're not using ARC)
NSString *path = [NSString stringWithString: #"/Users/me/Documents/My fols/recording_try"];
NSURL *dest = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
if(dest == nil)
{
NSLog( #"does not appear to be a valid NSURL object" );
return;
}
NSError * error = nil;
if([[NSFileManager defaultManager] createDirectoryAtURL: dest withIntermediateDirectories: YES attributes: nil error: &error] == YES)
{
dest = [dest URLByAppendingPathComponent: #"newMovie.mov"];
// now you can create the session plus input and output objects
// within this block
} else {
NSLog( #"was not able to create the directory which contains path %# - error is %#", path, [error localizedDescription] );
}
i´m using the AVAssetImageGenerator to get images from a movieclip without playing it before. Now i´ve got a question how to set up variables in the loop of a handler?
Is it possible?
I´m getting this error message and have no idea what does that mean. (google> no results).
"Variable is not assignable (missing
__block type specifier)"
So i have to ask the pro´s here.
Here´s the code. I want to save or return my generated imageData, so i can delete the "setImage" message within that following handler.
UIImage* thumbImg = [[UIImage alloc] init];
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error)
{
if (result != AVAssetImageGeneratorSucceeded)
{
NSLog(#"couldn't generate thumbnail, error:%#", error);
}
[button setImage:[UIImage imageWithCGImage:im] forState:UIControlStateNormal];
thumbImg = [[UIImage imageWithCGImage:im] retain];
[generator release];
};
Would be great to learn about that.
Thanks for your time.
1st of all it seems you don't need to init your thumbImg when its declared - UIImage object created in that line will be overwritten in block and will leak. Just init it with nil value.
Actual problem in your code is that variable you're going to change in block should be declared with __block specifier (as error message says). So your 1s line should be
__block UIImage* thumbImg = nil;