NSdata writeToURL not working - nsdata

i'm trying to save a NsData file into a directory. that is the code of my method:
- (void)cacheImage:(NSData *)imageData withTitle:(NSString *)title
{
NSURL *cacheURL = (NSURL *)[[self.fileMenager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0]; //we take the URL of the cache Directory and comvert the url of the cache directory into a string
NSURL *imageFolder = [cacheURL URLByAppendingPathComponent:PHOTO_CACHE_FOLDER];
if ([self.fileMenager isWritableFileAtPath:[cacheURL path]]) { //check if the cache directory is writable
if (![self.fileMenager createDirectoryAtURL:cacheURL withIntermediateDirectories:NO attributes:nil error:nil]) { //check if the directory of our image is already exist
NSURL * fileToWrite = [[imageFolder URLByAppendingPathComponent:title isDirectory:NO] URLByAppendingPathExtension:#"jpg"]; //take the complete url of image
if ([imageData writeToURL:fileToWrite atomically:YES]) //atomically = safe write
{
NSArray *debug = [self.fileMenager contentsOfDirectoryAtPath:[imageFolder path] error:nil];
for (NSURL *url in debug)
NSLog(#"url prooooo : %#",url);
}
}
}
}
that is an example of url (fileToWrite) where i try to write:
file://localhost/Users/MarcoMignano/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/93B0A0AC-EC13-4050-88CA-F46FBA11001E/Library/Caches/image_cache/Mozart%201.jpg
the point is simple, the method writeToURL return NO, i can't understand why, the url looks correct.
somebody can help my'
thank you.

The primary issue is that you are creating the wrong directory. You need to create the imageFolder directory.
if ([self.fileManager createDirectoryAtURL:imageFolder withIntermediateDirectories:YES attributes:nil error:nil]) {
And note that you do not want the ! in the if statement.

Related

Titanium Alloy Caching in Android/iOS? Or Preserving old views

Can we Cache Dynamically Created Lists or View till the webservices are called in background. I want to achieve something like the FaceBook App does. I know its possible in Android Core but wanted to try it in Titanium (Android and IOS).
I would further explain it,
Consider I have a app which has a list. Now When I open for first time, it will obviously hit the webservice and create a dynamic list.
Now I close the app and again open the app. The old list should be visible till the webservice provides any data.
Yes Titanium can do this. You should use a global variable like Ti.App.myList if it is just an array / a list / a variable. If you need to store more complex data like images or databases you should use the built-in file system. There is a really good Documentation on the Appcelerator website.
The procedure for you would be as follows:
Load your data for the first time
Store your data in your preferred way (Global variable, file system)
During future app starts read out your local list / data and display it until your sync is successfull.
You should consider to implement some variable to check wether any update is needed to minimize the network use (it saves energy and provides a better user experience if the users internet connection is slow).
if (response.state == "SUCCESS") {
Ti.API.info("Themes successfully checked");
Ti.API.info("RESPONSE TEST: " + response.value);
//Create a map of the layout names(as keys) and the corresponding url (as value).
var newImageMap = {};
for (var key in response.value) {
var url = response.value[key];
var filename = key + ".jpg"; //EDIT your type of the image
newImageMap[filename] = url;
}
if (Ti.App.ImageMap.length > 0) {
//Check for removed layouts
for (var image in Ti.App.imageMap) {
if (image in newImageMap) {
Ti.API.info("The image " + image + " is already in the local map");
//Do nothing
} else {
//Delete the removed layout
Ti.API.info("The image " + image + " is deleted from the local map");
delete Ti.App.imageMap[image];
}
}
//Check for new images
for (var image in newImageMap) {
if (image in Ti.App.imageMap) {
Ti.API.info("The image " + image + " is already in the local map");
//Do nothing
} else {
Ti.API.info("The image " + image + " is put into the local map");
//Put new image in local map
Ti.App.imageMap[image] = newImageMap[image];
}
}
} else {
Ti.App.imageMap = newImageMap;
}
//Check wether the file already exists
for (var key in response.value) {
var url = response.value[key];
var filename = key + ".png"; //EDIT YOUR FILE TYPE
Ti.API.info("URL: " + url);
Ti.API.info("FILENAME: " + filename);
imagesOrder[imagesOrder.length] = filename.match(/\d+/)[0]; //THIS SAVES THE FIRST NUMBER IN YOUR FILENAME AS ID
//Case1: download a new image
var file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, "/media/" + filename);
if (file.exists()) {
// Do nothing
Titanium.API.info("File " + filename + " exists");
} else {
// Create the HTTP client to download the asset.
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function() {
if (xhr.status == 200) {
// On successful load, take that image file we tried to grab before and
// save the remote image data to it.
Titanium.API.info("Successfully loaded");
file.write(xhr.responseData);
Titanium.API.info(file);
Titanium.API.info(file.getName());
};
};
// Issuing a GET request to the remote URL
xhr.open('GET', url);
// Finally, sending the request out.
xhr.send();
}
}
In addition to this code which should be placed in a success method of an API call, you need a global variable Ti.App.imageMap to store the map of keys and the corresponding urls. I guess you have to change the code a bit to fit your needs and your project but it should give you a good starting point.

fopen with UIImagePickerController image returns NULL on iOS

I am currently using a c++ library in my IOS application. Its main function is to transmit file via TCP/IP.
Now I am reaching the point that I can send/receive pure String data, but no image from imagePicker can be added. My fopen returns NULL;
hFile = fopen(imageRef.c_str(), "r+");
I am wondering whether Apple has restricted the way to get file from iphone?
I even tried to copy the chosen image file from image Picker to under "Documents" as below:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
chosenImage = info[UIImagePickerControllerEditedImage];
self.image.image = chosenImage;
// Create paths to output images
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/thepic.jpg"];
chosenImage = info[UIImagePickerControllerEditedImage];
[UIImageJPEGRepresentation(chosenImage, 1.0) writeToFile:jpgPath atomically:YES];
// Create file manager
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
// Write out the contents of home directory to console
NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"thepic.jpg"];
imageRef = [filePath cStringUsingEncoding:NSASCIIStringEncoding];
[picker dismissViewControllerAnimated:YES completion:NULL];
}

PKPass files getting replaced on Passbook for files in the same app

My App deals with downloading coupons & save into Passbook. But each time I download a different coupon, file is getting replaced on Passbook.
Below given is my code to add my coupons to Passbook :
Step 1 : Added 'PassKit' framework to the project & imported the same.
Step 2 : Added 'PKAddPassesViewControllerDelegate' on my h file.
Step 3 :
- (void) generatePass {
if (![PKPassLibrary isPassLibraryAvailable]) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"PassKit not available"
delegate:nil
cancelButtonTitle:#"Pitty"
otherButtonTitles: nil] show];
return;
}
else {
NSData *passData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://(url).pkpass"]];
NSError* error = nil;
PKPass *newPass = [[PKPass alloc] initWithData:passData
error:&error];
if (error!=nil) {
[[[UIAlertView alloc] initWithTitle:#"Passes error"
message:[error
localizedDescription]
delegate:nil
cancelButtonTitle:#"Ooops"
otherButtonTitles: nil] show];
return;
}
PKAddPassesViewController *addController =
[[PKAddPassesViewController alloc] initWithPass:newPass];
addController.delegate = self;
[self presentViewController:addController
animated:YES
completion:nil];
}
}
Passbook indexes passes by serialNumber and passTypeIdentifier. When adding a pass, if a pass with a matching serialNumber and passTypeIdentifier already exists in a user's pass library, that pass will be overwritten by the pass being added.
To add multiple passes for the same passTypeIdentifer you will have to generate a unique serialNumber for each new pass.

How to get the large picture from feed with graph api?

When loading the Facebook feeds from one page, if a picture exist in the feed, I want to display the large picture.
How can I get with the graph API ? The picture link in the feed is not the large one.
Thanks.
The Graph API photo object has a picture connection (similar to that the user object has):
“The album-sized view of the photo. […] Returns: HTTP 302 redirect to the URL of the picture.”
So requesting https://graph.facebook.com/{object-id-from-feed}/picture will redirect you to the album-sized version of the photo immediately. (Usefull not only for displaying it in a browser, but also if f.e. you want to download the image to your server, using cURL with follow_redirect option set.)
Edit:
Beginning with API v2.3, the /picture edge for feed posts is deprecated.
However, as a field the picture can still be requested – but it will be a small one.
But full_picture is available as well.
So /{object-id-from-feed}?fields=picture,full_picture can be used to request those, or they can be requested directly with the rest of feed data, like this /page-id/feed?fields=picture,full_picture,… (additional fields, such as message etc., must be specified the same way.)
What worked for me :
getting the picture link from the feed and replacing "_s.jpg" with "_n.jpg"
OK, I found a better way. When you retrieve a feed with the graph API, any feed item with a type of photo will have a field called object_id, which is not there for plain status type items. Query the Graph API with that ID, e.g. https://graph.facebook.com/1234567890. Note that the object ID isn't an underscore-separated value like the main ID of that feed item is.
The result of the object_id query will be a new JSON dictionary, where you will have a source attribute containing a URL for an image that has so far been big enough for my needs.
There is additionally an images array that contains more image URLs for different sizes of the image, but the sizes there don't seem to be predictable, and don't all actually correspond to the physical dimensions of the image behind that URL.
I still wish there was a way to do this with a single Graph API call, but it doesn't look like there is one.
For high res image links from:
Link posts
Video posts
Photo posts
I use the following:
Note: The reason I give the _s -> _o hack precedence over the object_id/picture approach is because the object_id approach was not returning results for all images.
var picture = result.picture;
if (picture) {
if (result.type === 'photo') {
if (picture.indexOf('_s') !== -1) {
console.log('CONVERTING');
picture = picture.replace(/_s/, '_o');
} else if (result.object_id) {
picture = 'https://graph.facebook.com/' + result.object_id + '/picture?width=9999&height=9999';
}
} else {
var qps = result.picture.split('&');
for (var i = 0; i < qps.length; i++) {
var qp = qps[i];
var matches = qp.match(/(url=|src=)/gi);
if (matches && matches.length > 0) picture = decodeURIComponent(qp.split(matches[0])[1]);
}
}
}
This is a new method to get a big image. it was born after the previews method doesn't works
/**
* return a big url of facebook
* works onky for type PHOTO
* #param picture
* #param is a post type link
* #return url of image
*/
#Transactional
public String getBigImageByFacebookPicture(String pictrue,Boolean link){
if(link && pictrue.contains("url=http")){
String url = pictrue.substring(pictrue.indexOf("url=") + 4);
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
return url;
}else{
try {
Document doc = Jsoup.connect(pictrue).get();
return doc.select("#fbPhotoImage").get(0).attr("src");
} catch (Exception e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
}
}
Enjoy your large image :)
Actually, you need two different solutions to fully fix this.
1] https://graph.facebook.com/{object_id}/picture
This solution works fine for images and videos posted to Facebook, but sadly, it returns small images in case the original image file was not uploaded to Facebook directly. (When posting a link to another site on your page for example).
2] The Facebook Graph API provides a way to get the full images in the feed itself for those external links. If you add 'full_picture' to the fields like in this example below when calling the API, you will be provided a link to the higher resolution version.
https://graph.facebook.com/your_facebook_id/posts?fields=id,link,full_picture,description,name&access_token=123456
Combining these two solutions I ended up filtering the input in PHP as follows:
if ( isset( $post['object_id'] ) ){
$image_url = 'https://graph.facebook.com/'.$post['object_id'].'/picture';
}else if ( isset( $post['full_picture'] ) ) {
$image_url = $post['full_picture'];
}else{
$image_url = '';
}
See: http://api-portal.anypoint.mulesoft.com/facebook/api/facebook-graph-api/docs/reference/pictures
Just put "?type=large" after the URL to get the big picture.
Thanks to #mattdlockyer for the JS solution. Here is a similar thing in PHP:
$posts = $facebook->api('/[page]/posts/', 'get');
foreach($posts['data'] as $post)
{
if(stristr(#$post['picture'], '_s.'))
{
$post['picture'] = str_replace('_s.', '_n.', #$post['picture']);
}
if(stristr(#$post['picture'], 'url='))
{
parse_str($post['picture'], $picturearr);
if($picturearr['url'])
$post['picture'] = $picturearr['url'];
}
//do more stuff with $post and $post['picture'] ...
}
After positive comment from #Lachezar Todorov I decided to post my current approach (including paging and using Json.NET ;):
try
{
FacebookClient fbClient = new FacebookClient(HttpContext.Current.Session[SessionFacebookAccessToken].ToString());
JObject posts = JObject.Parse(fbClient.Get(String.Format("/{0}/posts?fields=message,picture,link,attachments", FacebookPageId)).ToString());
JArray newsItems = (JArray)posts["data"];
List<NewsItem> result = new List<NewsItem>();
while (newsItems.Count > 0)
{
result.AddRange(GetItemsFromJsonData(newsItems));
if (result.Count > MaxNewsItems)
{
result.RemoveRange(MaxNewsItems, result.Count - MaxNewsItems);
break;
}
JToken paging = posts["paging"];
if (paging != null)
{
if (paging["next"] != null)
{
posts = JObject.Parse(fbClient.Get(paging.Value<String>("next")).ToString());
newsItems = (JArray)posts["data"];
}
}
}
return result;
}
And the helper method to retieve individual items:
private static IEnumerable<NewsItem> GetItemsFromJsonData(IEnumerable<JToken> items)
{
List<NewsItem> newsItems = new List<NewsItem>();
foreach (JToken item in items.Where(item => item["message"] != null))
{
NewsItem ni = new NewsItem
{
Message = item.Value<String>("message"),
DateTimeCreation = item.Value<DateTime?>("created_time"),
Link = item.Value<String>("link"),
Thumbnail = item.Value<String>("picture"),
// http://stackoverflow.com/questions/28319242/simplify-looking-up-nested-json-values-with-json-net/28359155#28359155
Image = (String)item.SelectToken("attachments.data[0].media.image.src") ?? (String)item.SelectToken("attachments.data[0].subattachments.data[0].media.image.src")
};
newsItems.Add(ni);
}
return newsItems;
}
NewsItem class I use:
public class NewsItem
{
public String Message { get; set; }
public DateTime? DateTimeCreation { get; set; }
public String Link { get; set; }
public String Thumbnail { get; set; }
public String Image { get; set; }
}

HTTP/1.1 200 213 on Tomcat while uploading jpeg file using RESTKit

All,
I am using RestKit for iOS to upload a JPEG file to my Java web service. I referred to this
tutorial for developing file upload web service and it works perfectly fine when i use it through my web browser.
However, when i try to upload a file using RESTKit then in TOMCAT logs i get HTTP/1.1 200 213 status code and my file is not uploaded.
Here is my RESTKit code:
RKObjectManager* manager = [RKObjectManager sharedManager];
RKObjectLoader* objectLoader = [manager objectLoaderWithResourcePath:#"/fileuploaded" delegate:self];
objectLoader.method = RKRequestMethodPOST;
UIImage *image = [UIImage imageNamed:#"rental_car_bill.jpeg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
// attach image
RKParams *params = [RKParams paramsWithDictionary:(NSDictionary*)objectLoader.params];
RKParamsAttachment *attachment = [params setData:imageData
MIMEType:#"image/jpeg" forParam:#"photo"];
attachment.fileName = #"samplejpeg";
objectLoader.params = params;
objectLoader.targetObject = self;
[objectLoader send];
EDIT:
Above implementation does work and the file does get uploaded. However, in the delegate method: - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
After it gets out of the scope of this, then my application crashes at [RKObjectLoader dealloc];
To upload pictures using restkit I use the following methods, I prefer using blocks to avoid some problems on my app, maybe that way you can avoid your crash:
- (void) upload: (KFMedia *) pic onLoad:(RKObjectLoaderDidLoadObjectBlock) loadBlock onError:(RKRequestDidFailLoadWithErrorBlock)failBlock{
//pic.image returns an UIImage
RKParams* imageParams = [RKParams params];
NSData* imageData = UIImageJPEGRepresentation(pic.image, 0.7f);
[imageParams setData:imageData MIMEType:#"image/jpg" forParam:#"FileUpload"];
NSString *resourcePath = #"/api/upload/";
//My API Server will return a JSON that represents my KFMedia Class after uploading the image, so here I get the propper mapping for that
RKObjectMapping *mapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[KFMedia class]];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:resourcePath usingBlock:^(RKObjectLoader *loader) {
loader.method = RKRequestMethodPOST;
loader.params = imageParams;
[self settingsForLoader:loader withMapping:mapping onLoad:loadBlock onError:failBlock];
}];
}
- (void) settingsForLoader: (RKObjectLoader *) loader withMapping: (RKObjectMapping *) mapping onLoad:(RKObjectLoaderDidLoadObjectBlock) loadBlock onError:(RKRequestDidFailLoadWithErrorBlock)failBlock{
loader.objectMapping = mapping;
loader.delegate = self;
loader.onDidLoadObject = loadBlock;
loader.onDidFailWithError = ^(NSError * error){
NSLog(#"%#",error);
};
loader.onDidFailLoadWithError = failBlock;
loader.onDidLoadResponse = ^(RKResponse *response) {
[self fireErrorBlock:failBlock onErrorInResponse:response];
};
}