I've created NSManagedObject* imagesArrayData that stores strings (paths) to images stored in the documents directory:
- (void)setImagesArray:(NSMutableArray *)imagesArray {
NSMutableArray* newImagesArray = [NSMutableArray new];
int i = 1;
for (UIImage* image in imagesArray) {
//generate path to createdFile
NSString* fileName = [NSString stringWithFormat:#"%#_%d", self.name, i];
NSString* filePath = [self documentsPathForFileName:fileName];
//save image to disk
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
//add image path to CoreData
[newImagesArray addObject:filePath];
i++;
}
//set new value of imagesArray
imagesArrayData = [NSKeyedArchiver archivedDataWithRootObject:newImagesArray];
I am now not showing pathsToImages in header file, but property imagesArray:
-(NSMutableArray*) imagesArray {
NSMutableArray* images = [NSMutableArray new];
NSArray* imagePaths = [NSKeyedUnarchiver unarchiveObjectWithData:imagesArrayData];
for (NSString* imagePath in imagePaths) {
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[images addObject:image];
}
return images;
The problem is, that whenever I want to get to [imagesArray objectatIndex:xxx], the imagesArray getter is called, and it takes time to recreate the full array. When trying to switch fast between images, the UI slows down.
What would be the elegant way to overcome this problem? Maybe creating another array full of images and updating it from time to time? Maybe something else? Please, help.
One thing you could do is refactor your getter to lazily load the array. If it is already defined, simply return it. If not, build it:
-(NSMutableArray*) imagesArray
{
if (!_imagesArray)
{
NSMutableArray* _imagesArray = [NSMutableArray new];
NSArray* imagePaths =
[NSKeyedUnarchiver unarchiveObjectWithData: imagesArrayData];
for (NSString* imagePath in imagePaths)
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[_imagesArray addObject:image];
}
return _imagesArray;
}
I'm not sure what you mean about updating an array of images from time to time.
If your array of image names changes you will need some method to respond to those changes.
I want to convert array of Image Paths which are in document directory into Encoded baSE 64 string.
Here is my code
NSArray *recipeImages = [savedImagePath valueForKey:#"Image"];
this array contains path of the images (MULTIPLE IMAGES).
This is how array looks in Logs.
Saved Images == (
"/Users/ZAL02M/Library/Developer/CoreSimulator/Devices/F1F3C01E-8686-4367-82FB-80B003E2F416/data/Containers/Data/Application/694494B1-0DCA-497A-B8B0-586276EEF240/Documents/cached0.png",
"/Users/ZAL02M/Library/Developer/CoreSimulator/Devices/F1F3C01E-8686-4367-82FB-80B003E2F416/data/Containers/Data/Application/694494B1-0DCA-497A-B8B0-586276EEF240/Documents/cached1.png"
)
How to make base64 string ???
Try this to cycle all your images and save each encoded string into a new array:
NSMutableArray *encodedImages = [NSMutableArray new];
for (NSString *path in recipeImages)
{
UIImage *image = [UIImage imageWithContentsOfFile:path];
NSData *imageData = UIImagePNGRepresentation(image);
NSString *dataString = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[encodedImages addObject:dataString];
}
Convert your ImagePaths (Strings) to NSData and from NSData back to string via base64EncodedStringWithOptions:
Here the code:
NSArray *recipeImages = [savedImagePath valueForKey:#"Image"];
NSMutableArray *mutableBase64StringsArray = #[].mutableCopy;
for (NSString *imagePath in recipeImages)
{
NSData *imagePathData = [imagePath dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64ImagePath = [imagePathData base64EncodedStringWithOptions:0];
[mutableBase64StringsArray addObject:base64ImagePath];
}
In the mutableBase64StringsArray you have all imagePaths as base64 encoded strings.
Look at this post from SO for more explanations: Base64 Decoding in iOS 7+
you can try this
Encoding :
- (NSString *)encodeToBase64String:(UIImage *)image {
return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
Decoding :
- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
return [UIImage imageWithData:data];
}
To get image from your path you can use this code
NSString* imagePath = [recipeImages objectAtIndex:i];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imagePath];
Then add encoded content to your array.
Hope it helps.
I created a method which gets data from a server, everything works fine except when I try to set string to for example UILabel or UITextView, nothing shows and changed ! here is my code :
- (void)viewDidLoad
{
[super viewDidLoad];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:_eTitle1.text image:_eImage1 description:_eNews1.text];
}
Getting Data :
-(void)getDataFromURL:(NSString*)url setTitle:(NSString*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions {
NSURL *URL = [NSURL URLWithString:url];
NSError *error1;
NSString *strPageContent = [NSString stringWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error1];
strPageContent = [strPageContent gtm_stringByUnescapingFromHTML];
if ([strPageContent rangeOfString:#"<plist version=\"1.0\">"].location != NSNotFound) {
NSRange range = [strPageContent rangeOfString:#"<plist version=\"1.0\">"];
strPageContent = [strPageContent substringWithRange:NSMakeRange(range.location+range.length, strPageContent.length-(range.location+range.length))];
strPageContent = [strPageContent stringByReplacingOccurrencesOfString:#"</plist>" withString:#""];
}
NSError *error = nil;
NSDictionary *dict = [XMLReader dictionaryForXMLString:strPageContent options:XMLReaderOptionsProcessNamespaces
error:&error];
if ([dict count]>0) {
NSDictionary *dictInner = [dict objectForKey:#"dict"];
NSArray *arrValues = [dictInner objectForKey:#"string"];
NSString * strTitle = [[arrValues objectAtIndex:0] objectForKey:#"text"];
NSString *strImage = [[arrValues objectAtIndex:1] objectForKey:#"text"];
NSString * strDescription = [[arrValues objectAtIndex:2] objectForKey:#"text"];
eTitle = strTitle;
eDescriptions = strDescription;
// [eImages setImageWithURL:[NSURL URLWithString:strImage]
// placeholderImage:[UIImage imageNamed:#"loadingPad.jpg"]];
NSLog(#"Title: %# | Image: %# | Desc: %#",eTitle,strImage,eDescriptions);
}
}
compiler gives me the right information ! but these string could not set to my lable , IF I put my lable's string into the method it works !!! :
_eTitle1.text = strTitle ;
It's completely normal: when you pass the "text" object to the method, you are passing the pointer to it. Assigning to it directly another NSString object will just assign a new pointer. In order to have side effect on a string you gotta use NSMutableString, but the UILabel has just an immutable NSString for the text attribute. So the only solution is to pass the UILabel or pass an initialized empty mutable string inside the method, change the content via [eTitleText setString:strTitle] and then, outside the method, assign it to the UILabel text attribute.
So, either you change the method like this (as you already did):
-(void)getDataFromURL:(NSString*)url setTitle:(UILabel*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions {
...
eTitle.text = strTitle;
...
and using it like this:
- (void)viewDidLoad
{
[super viewDidLoad];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:_eTitle1 image:_eImage1 description:_eNews1.text];
}
Or you can go this other way:
-(void)getDataFromURL:(NSString*)url setTitle:(NSMutableString*)eTitle
image:(UIImageView*)eImages description:(NSString*)eDescriptions
...
[eTitle setString:strTitle];
...
and using it like this:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableString *titleText = [NSMutableString new];
[self getDataFromURL:#"http://somesites.net/panel/services?action=events&num=1"
setTitle:titleText image:_eImage1 description:_eNews1.text];
eTitle1.text = titleText;
}
With all the URL-handling objects lying around in the standard Cocoa libraries (NSURL, NSMutableURL, NSMutableURLRequest, etc), I know I must be overlooking an easy way to programmatically compose a GET request.
Currently I'm manually appending "?" followed by name value pairs joined by "&", but all of my name and value pairs need to be manually encoded so NSMutableURLRequest doesn't fail entirely when it tries to connect to the URL.
This feels like something I should be able to use a pre-baked API for.... is there anything out of the box to append an NSDictionary of query parameters to an NSURL? Is there another way I should approach this?
Introduced in iOS8 and OS X 10.10 is NSURLQueryItem, which can be used to build queries. From the docs on NSURLQueryItem:
An NSURLQueryItem object represents a single name/value pair for an item in the query portion of a URL. You use query items with the queryItems property of an NSURLComponents object.
To create one use the designated initializer queryItemWithName:value: and then add them to NSURLComponents to generate an NSURL. For example:
NSURLComponents *components = [NSURLComponents componentsWithString:#"http://stackoverflow.com"];
NSURLQueryItem *search = [NSURLQueryItem queryItemWithName:#"q" value:#"ios"];
NSURLQueryItem *count = [NSURLQueryItem queryItemWithName:#"count" value:#"10"];
components.queryItems = #[ search, count ];
NSURL *url = components.URL; // http://stackoverflow.com?q=ios&count=10
Notice that the question mark and ampersand are automatically handled. Creating an NSURL from a dictionary of parameters is as simple as:
NSDictionary *queryDictionary = #{ #"q": #"ios", #"count": #"10" };
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in queryDictionary) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryDictionary[key]]];
}
components.queryItems = queryItems;
I've also written a blog post on how to build URLs with NSURLComponents and NSURLQueryItems.
You can create a category for NSDictionary to do this -- there isn't a standard way in the Cocoa library that I could find either. The code that I use looks like this:
// file "NSDictionary+UrlEncoding.h"
#import <cocoa/cocoa.h>
#interface NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString;
#end
with this implementation:
// file "NSDictionary+UrlEncoding.m"
#import "NSDictionary+UrlEncoding.h"
// helper function: get the string form of any object
static NSString *toString(id object) {
return [NSString stringWithFormat: #"%#", object];
}
// helper function: get the url encoded string form of any object
static NSString *urlEncode(id object) {
NSString *string = toString(object);
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}
#implementation NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString {
NSMutableArray *parts = [NSMutableArray array];
for (id key in self) {
id value = [self objectForKey: key];
NSString *part = [NSString stringWithFormat: #"%#=%#", urlEncode(key), urlEncode(value)];
[parts addObject: part];
}
return [parts componentsJoinedByString: #"&"];
}
#end
I think the code's pretty straightforward, but I discuss it in some more detail at http://blog.ablepear.com/2008/12/urlencoding-category-for-nsdictionary.html.
I wanted to use Chris's answer, but it wasn't written for Automatic Reference Counting (ARC) so I updated it. I thought I'd paste my solution in case anyone else has this same issue. Note: replace self with the instance or class name where appropriate.
+(NSString*)urlEscapeString:(NSString *)unencodedString
{
CFStringRef originalStringRef = (__bridge_retained CFStringRef)unencodedString;
NSString *s = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,originalStringRef, NULL, (CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ", kCFStringEncodingUTF8);
CFRelease(originalStringRef);
return s;
}
+(NSString*)addQueryStringToUrlString:(NSString *)urlString withDictionary:(NSDictionary *)dictionary
{
NSMutableString *urlWithQuerystring = [[NSMutableString alloc] initWithString:urlString];
for (id key in dictionary) {
NSString *keyString = [key description];
NSString *valueString = [[dictionary objectForKey:key] description];
if ([urlWithQuerystring rangeOfString:#"?"].location == NSNotFound) {
[urlWithQuerystring appendFormat:#"?%#=%#", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
} else {
[urlWithQuerystring appendFormat:#"&%#=%#", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
}
}
return urlWithQuerystring;
}
The other answers work great if the values are strings, however if the values are dictionaries or arrays then this code will handle that.
Its important to note that there is no standard way of passing an array/dictionary via the query string but PHP handles this output just fine
-(NSString *)serializeParams:(NSDictionary *)params {
/*
Convert an NSDictionary to a query string
*/
NSMutableArray* pairs = [NSMutableArray array];
for (NSString* key in [params keyEnumerator]) {
id value = [params objectForKey:key];
if ([value isKindOfClass:[NSDictionary class]]) {
for (NSString *subKey in value) {
NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)[value objectForKey:subKey],
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
[pairs addObject:[NSString stringWithFormat:#"%#[%#]=%#", key, subKey, escaped_value]];
}
} else if ([value isKindOfClass:[NSArray class]]) {
for (NSString *subValue in value) {
NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)subValue,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
[pairs addObject:[NSString stringWithFormat:#"%#[]=%#", key, escaped_value]];
}
} else {
NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)[params objectForKey:key],
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
[pairs addObject:[NSString stringWithFormat:#"%#=%#", key, escaped_value]];
[escaped_value release];
}
}
return [pairs componentsJoinedByString:#"&"];
}
Examples
[foo] => bar
[translations] =>
{
[one] => uno
[two] => dos
[three] => tres
}
foo=bar&translations[one]=uno&translations[two]=dos&translations[three]=tres
[foo] => bar
[translations] =>
{
uno
dos
tres
}
foo=bar&translations[]=uno&translations[]=dos&translations[]=tres
I refactored and converted to ARC answer by AlBeebe
- (NSString *)serializeParams:(NSDictionary *)params {
NSMutableArray *pairs = NSMutableArray.array;
for (NSString *key in params.keyEnumerator) {
id value = params[key];
if ([value isKindOfClass:[NSDictionary class]])
for (NSString *subKey in value)
[pairs addObject:[NSString stringWithFormat:#"%#[%#]=%#", key, subKey, [self escapeValueForURLParameter:[value objectForKey:subKey]]]];
else if ([value isKindOfClass:[NSArray class]])
for (NSString *subValue in value)
[pairs addObject:[NSString stringWithFormat:#"%#[]=%#", key, [self escapeValueForURLParameter:subValue]]];
else
[pairs addObject:[NSString stringWithFormat:#"%#=%#", key, [self escapeValueForURLParameter:value]]];
}
return [pairs componentsJoinedByString:#"&"];
}
- (NSString *)escapeValueForURLParameter:(NSString *)valueToEscape {
return (__bridge_transfer NSString *) CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef) valueToEscape,
NULL, (CFStringRef) #"!*'();:#&=+$,/?%#[]", kCFStringEncodingUTF8);
}
If you are already using AFNetworking (as was the case with me), you can use it's class AFHTTPRequestSerializer to create the required NSURLRequest.
[[AFHTTPRequestSerializer serializer] requestWithMethod:#"GET" URLString:#"YOUR_URL" parameters:#{PARAMS} error:nil];
In case you only require the URL for your work, use NSURLRequest.URL.
Here is a simple example in Swift (iOS8+):
private let kSNStockInfoFetchRequestPath: String = "http://dev.markitondemand.com/Api/v2/Quote/json"
private func SNStockInfoFetchRequestURL(symbol:String) -> NSURL? {
if let components = NSURLComponents(string:kSNStockInfoFetchRequestPath) {
components.queryItems = [NSURLQueryItem(name:"symbol", value:symbol)]
return components.URL
}
return nil
}
I took Joel's recommendation of using URLQueryItems and turned into a Swift Extension (Swift 3)
extension URL
{
/// Creates an NSURL with url-encoded parameters.
init?(string : String, parameters : [String : String])
{
guard var components = URLComponents(string: string) else { return nil }
components.queryItems = parameters.map { return URLQueryItem(name: $0, value: $1) }
guard let url = components.url else { return nil }
// Kinda redundant, but we need to call init.
self.init(string: url.absoluteString)
}
}
(The self.init method is kinda cheesy, but there was no NSURL init with components)
Can be used as
URL(string: "http://www.google.com/", parameters: ["q" : "search me"])
I've got another solution:
http://splinter.com.au/build-a-url-query-string-in-obj-c-from-a-dict
+(NSString*)urlEscape:(NSString *)unencodedString {
NSString *s = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8);
return [s autorelease]; // Due to the 'create rule' we own the above and must autorelease it
}
// Put a query string onto the end of a url
+(NSString*)addQueryStringToUrl:(NSString *)url params:(NSDictionary *)params {
NSMutableString *urlWithQuerystring = [[[NSMutableString alloc] initWithString:url] autorelease];
// Convert the params into a query string
if (params) {
for(id key in params) {
NSString *sKey = [key description];
NSString *sVal = [[params objectForKey:key] description];
// Do we need to add ?k=v or &k=v ?
if ([urlWithQuerystring rangeOfString:#"?"].location==NSNotFound) {
[urlWithQuerystring appendFormat:#"?%#=%#", [Http urlEscape:sKey], [Http urlEscape:sVal]];
} else {
[urlWithQuerystring appendFormat:#"&%#=%#", [Http urlEscape:sKey], [Http urlEscape:sVal]];
}
}
}
return urlWithQuerystring;
}
You can then use it like so:
NSDictionary *params = #{#"username":#"jim", #"password":#"abc123"};
NSString *urlWithQuerystring = [self addQueryStringToUrl:#"https://myapp.com/login" params:params];
-(NSString*)encodeDictionary:(NSDictionary*)dictionary{
NSMutableString *bodyData = [[NSMutableString alloc]init];
int i = 0;
for (NSString *key in dictionary.allKeys) {
i++;
[bodyData appendFormat:#"%#=",key];
NSString *value = [dictionary valueForKey:key];
NSString *newString = [value stringByReplacingOccurrencesOfString:#" " withString:#"+"];
[bodyData appendString:newString];
if (i < dictionary.allKeys.count) {
[bodyData appendString:#"&"];
}
}
return bodyData;
}
Yet another solution, if you use RestKit there's a function in RKURLEncodedSerialization called RKURLEncodedStringFromDictionaryWithEncoding that does exactly what you want.
Simple way of converting NSDictionary to url query string in Objective-c
Ex: first_name=Steve&middle_name=Gates&last_name=Jobs&address=Palo Alto, California
NSDictionary *sampleDictionary = #{#"first_name" : #"Steve",
#"middle_name" : #"Gates",
#"last_name" : #"Jobs",
#"address" : #"Palo Alto, California"};
NSMutableString *resultString = [NSMutableString string];
for (NSString* key in [sampleDictionary allKeys]){
if ([resultString length]>0)
[resultString appendString:#"&"];
[resultString appendFormat:#"%#=%#", key, [sampleDictionary objectForKey:key]];
}
NSLog(#"QueryString: %#", resultString);
Hope will help :)
If you are already using AFNetwork, you can use their built in serializer to to produce an encoded URL;
NSString *baseURL = #"https://api.app.com/parse";
NSDictionary *mutableParameters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"true",#"option1", data, #"option2", token, #"token", #"3.0", #"app", nil];
NSURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:#"GET" URLString:baseURL parameters:mutableParameters error:nil];
NSString *urlPath = request.URL.absoluteString;
NSLog(#"%#", urlPath); // https://api.app.com/parse?option1=true&option2=datavalue&token=200%3ATEST%3AENCODE ....
Note; this is an extension to an above answer. The edit queue is full so cannot be added to the existing answer.
I've a tableview which has list of images and image thumbnail (image list and thumbnails are parsed from JSON object), I'm adding image data objects to imagesArray like this -
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imagesArray addObject:imageDataObject];
ImageData object
#property (nonatomic, strong) NSString* imageId;
#property (nonatomic, strong) NSData* imageData;
allImagesArray like this
[ImageData object1,ImageData object2,....]
I want to assign imageData of the object from this array based on selectedImageId to
UIImage* image =[[UIImage alloc] initWithData:........];
I'm not able to think of a way to get to that imageData based on selectedImageId
Please help.
Update -
Thank you all for the help, I could do it.
One of the possible way will be, iterate through the array, find your selectedImageId from the dictionary and use it.
Example:
ImageData *imageDataObject = nil;
for(int i=0; i<allImagesArray.count;i++){
NSDictionary *dict= allImagesArray[i];
imageDataObject = [dict objectForKey:selectedImageId];
if(imageDataObject != nil){
UIImage* image =[[UIImage alloc] initWithData:........];
//do whatever
break;
}
}
As per your EDIT:
What you have is an array of ImageData objects [ImageData1,ImageData2,...]. For each ImageData object, you have imageId and imageData property and what you want is simply compare the selectedImageId with this imageId and get the imageData from that.
So for that, in your PPImageViewController, you can iterate the allImagesArray like this and get the imageData.
for(ImageData* imgDataObj in self.allImagesArray){
if([imgDataObj.imageId isEqualToString:self.selectedImageId]){
UIImage* image =[[UIImage alloc] initWithData:imgDataObj.imageData];
}
}
So you have:
NSArray* allImagesArray = #[#{#"some_image_id_in_NSString_1":#"the data in NSData 1"}, #{#"some_image_id_in_NSString_2":#"the data in NSData 2"}];
As a property of PPImageViewController.
Assuming the imageid is an NSString and imagedata is NSData, you can create a method something like this on PPImageViewController:
- (UIImage*) findSelectedImage
{
UIImage* selectedImage;
for(NSDictionary* d in allImagesArray)
{
NSString* currentKey = [[d allKeys] objectAtIndex:0];
if([currentKey isEqualToString:[self selectedImageId]])
{
NSData* imageData = [d objectForKey:currentKey];
selectedImage = [UIImage imageWithData:imageData];
break;
}
}
return selectedImage;
}
Then call it like this, maybe on your viewDidLoad method:
UIImage* selectedImage = [self findSelectedImage];
Hope it help.
I see you are adding ImageData objects directly into the Array. You could have just used a NSDictionary instead. The key can be imageID (assuming it to be unique) and value will be the imageData object. Then pass the dictionary instead of array to PPImageViewController.
NSMutableDictionary *imageData = [NSMutableDictionary dictionary];
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imageData setObject:imageDataObject forKey:imageId];
And then within PPImageViewController, you can easily get the imageDataObject based on selected imageID like this:
ImageData *imageDataObject = allImagesDictionary[selectedImageID];
EDIT:
NSArray *imageIndexes = [allImagesDictionary allKeys];
// Now use imageIndexes to populate your table. This will guarantee the order
// Fetch the imageId
selectedImageID = imageIndexes[indexPath.row];
// Fetch the imageData
ImageData *imageDataObject = allImagesDictionary[selectedImageID];