data disappear out of UNIUrlConnection - ios

What I'm trying to do is to pass data from my Objective-C to my swift file.
Recently, when I have successfully connected my objective c file with my swift file, I can print data that get from UNIUrlConnection(which means the connection between swift and objective-c works fine).
Then I create a NSMutableDictionary object and add those data into NSMutableDictionary. I want to pass this NSMutableDictionary object to my swift file so that I can output them on my viewController.
However, the NSMutableDictionary contains correct data within the UNIUrlConnection but then contains none out of UNIUrlConnection. Thus the NSMutableDictionary passed to swift file would always contain no data. How can I solve this?
This is my objective c file.
#import <Foundation/Foundation.h>
#import <UNIRest.h>
#import "findByIngredients.h"
#implementation findByIngredients
-(NSMutableDictionary*) connectAPI:(NSString*) ingredients Number:(NSString*) number{
NSMutableDictionary *temp = [NSMutableDictionary dictionaryWithCapacity:10];
NSString* url = #"https://spoonacular-recipe-food-nutrition-v1.p.mashape.com/recipes/findByIngredients?fillIngredients=false";
if (![ingredients isEqual: #""]) {
NSString* ingre = #"&ingredients=";
ingre = [ingre stringByAppendingString:ingredients];
url = [url stringByAppendingString:ingre];
}
else {
NSString* ingre = #"&ingredients=<required>";
url = [url stringByAppendingString:ingre];
}
NSString* LL = #"&limitLicense=false";
url = [url stringByAppendingString:LL];
if (![number isEqual: #""]) {
NSString* numberOfReturn = #"&number=";
numberOfReturn = [numberOfReturn stringByAppendingString:number];
url = [url stringByAppendingString:numberOfReturn];
}
NSString* ranking = #"&ranking=1";
url = [url stringByAppendingString:ranking];
// These code snippets use an open-source library. http://unirest.io/objective-c
NSDictionary *headers = #{#"X-Mashape-Key": #"KEY", #"Accept": #"application/json"};
UNIUrlConnection *asyncConnection = [[UNIRest get:^(UNISimpleRequest *request) {
[request setUrl:url];
[request setHeaders:headers];
}] asJsonAsync:^(UNIHTTPJsonResponse *response, NSError *error) {
NSInteger code = response.code;
NSDictionary *responseHeaders = response.headers;
UNIJsonNode *body = response.body;
NSData *rawBody = response.rawBody;
if (rawBody) {
id allKeys = [NSJSONSerialization JSONObjectWithData:rawBody options:0 error:&error];
for (int i=0; i<[allKeys count]; i++) {
NSDictionary *arrayResult = [allKeys objectAtIndex:i];
// NSString* myNewString = [NSString stringWithFormat:#"%d", i];
NSString *key = [arrayResult objectForKey:#"id"];
NSString *value = [arrayResult objectForKey:#"title"];
[temp setObject:value forKey:key];
NSLog(#"id=%#",[arrayResult objectForKey:#"id"]);
NSLog(#"title=%#",[arrayResult objectForKey:#"title"]);
}
}
int size = [temp count];
NSLog(#"temp size is %d",size);
NSLog(#"successfully test API");
}];
// int size = [temp count];
// NSLog(#"temp size is %d",size);
return temp;
}
#end
Here the size of temp within UNIUrlConnection is correct. But if I put the size before return (which I comment out), it shows 0, which is wrong.
This is my swift file.
#IBAction func search(_ sender: Any) {
let ingreArr = IngredientsText.text.components(separatedBy: [",", " "])
var ingre:String = ingreArr[0]
let sep:String = "%2C"
for (index,element) in ingreArr.enumerated() {
if (index >= 1) {
ingre = ingre + sep + element
}
}
let test = findByIngredients()
// test.connectAPI(ingre, number: NumberOfResults.text)
let result: Dictionary = test.connectAPI(ingre, number: NumberOfResults.text) as Dictionary
let num:Int = result.count
print(num)
}
The num is 0.

Related

I'm not able to resume download task in NSURLSession

I have create a demo for downloading a file from the server it is working fine with foreground and background, but when I'm going to resume it, It will giving below Error
I have stcuk here could help me so solved it, I search in internet but I couldn't find anything helpful.
Download file and Pause Downlaod is working fine I have issue to resume it.
Task <3AE5BF24-3A4E-4713-8FC2-A0032022C913>.<6> finished with error [-3003] Error Domain=NSURLErrorDomain Code=-3003 "(null)" UserInfo={_NSURLErrorRelatedURLSessionTaskErrorKey=(
"BackgroundDownloadTask <3AE5BF24-3A4E-4713-8FC2-A0032022C913>.<6>"
), _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDownloadTask <3AE5BF24-3A4E-4713-8FC2-A0032022C913>.<6>}
Here is the final Xcode project
Downlaod xcode project
#import "NSURLSession+ResumeData.h"
#import <UIKit/UIKit.h>
#define IS_IOS10ORLATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10)
#pragma mark- private
static NSData * correctRequestData(NSData *data) {
if (!data) {
return nil;
}
// return the same data if it's correct
if ([NSKeyedUnarchiver unarchiveObjectWithData:data] != nil) {
return data;
}
NSMutableDictionary *archive = [[NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil] mutableCopy];
if (!archive) {
return nil;
}
NSInteger k = 0;
id objectss = archive[#"$objects"];
while ([objectss[1] objectForKey:[NSString stringWithFormat:#"$%ld",k]] != nil) {
k += 1;
}
NSInteger i = 0;
while ([archive[#"$objects"][1] objectForKey:[NSString stringWithFormat:#"__nsurlrequest_proto_prop_obj_%ld",i]] != nil) {
NSMutableArray *arr = archive[#"$objects"];
NSMutableDictionary *dic = arr[1];
id obj = [dic objectForKey:[NSString stringWithFormat:#"__nsurlrequest_proto_prop_obj_%ld",i]];
if (obj) {
[dic setValue:obj forKey:[NSString stringWithFormat:#"$%ld",i+k]];
[dic removeObjectForKey:[NSString stringWithFormat:#"__nsurlrequest_proto_prop_obj_%ld",i]];
[arr replaceObjectAtIndex:1 withObject:dic];
archive[#"$objects"] = arr;
}
i++;
}
if ([archive[#"$objects"][1] objectForKey:#"__nsurlrequest_proto_props"] != nil) {
NSMutableArray *arr = archive[#"$objects"];
NSMutableDictionary *dic = arr[1];
id obj = [dic objectForKey:#"__nsurlrequest_proto_props"];
if (obj) {
[dic setValue:obj forKey:[NSString stringWithFormat:#"$%ld",i+k]];
[dic removeObjectForKey:#"__nsurlrequest_proto_props"];
[arr replaceObjectAtIndex:1 withObject:dic];
archive[#"$objects"] = arr;
}
}
// Rectify weird "NSKeyedArchiveRootObjectKey" top key to NSKeyedArchiveRootObjectKey = "root"
if ([archive[#"$top"] objectForKey:#"NSKeyedArchiveRootObjectKey"] != nil) {
[archive[#"$top"] setObject:archive[#"$top"][#"NSKeyedArchiveRootObjectKey"] forKey: NSKeyedArchiveRootObjectKey];
[archive[#"$top"] removeObjectForKey:#"NSKeyedArchiveRootObjectKey"];
}
// Reencode archived object
NSData *result = [NSPropertyListSerialization dataWithPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil];
return result;
}
static NSMutableDictionary *getResumeDictionary(NSData *data) {
NSMutableDictionary *iresumeDictionary = nil;
if (IS_IOS10ORLATER) {
id root = nil;
id keyedUnarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
#try {
root = [keyedUnarchiver decodeTopLevelObjectForKey:#"NSKeyedArchiveRootObjectKey" error:nil];
if (root == nil) {
root = [keyedUnarchiver decodeTopLevelObjectForKey:NSKeyedArchiveRootObjectKey error:nil];
}
} #catch(NSException *exception) {
}
[keyedUnarchiver finishDecoding];
iresumeDictionary = [root mutableCopy];
}
if (iresumeDictionary == nil) {
iresumeDictionary = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil];
}
return iresumeDictionary;
}
static NSData *correctResumeData(NSData *data) {
NSString *kResumeCurrentRequest = #"NSURLSessionResumeCurrentRequest";
NSString *kResumeOriginalRequest = #"NSURLSessionResumeOriginalRequest";
if (data == nil) {
return nil;
}
NSMutableDictionary *resumeDictionary = getResumeDictionary(data);
if (resumeDictionary == nil) {
return nil;
}
resumeDictionary[kResumeCurrentRequest] = correctRequestData(resumeDictionary[kResumeCurrentRequest]);
resumeDictionary[kResumeOriginalRequest] = correctRequestData(resumeDictionary[kResumeOriginalRequest]);
NSData *result = [NSPropertyListSerialization dataWithPropertyList:resumeDictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nil];
return result;
}
#implementation NSURLSession (ResumeData)
- (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData {
NSString *kResumeCurrentRequest = #"NSURLSessionResumeCurrentRequest";
NSString *kResumeOriginalRequest = #"NSURLSessionResumeOriginalRequest";
NSData *cData = correctResumeData(resumeData);
cData = cData ? cData:resumeData;
NSURLSessionDownloadTask *task = [self downloadTaskWithResumeData:cData];
NSMutableDictionary *resumeDic = getResumeDictionary(cData);
if (resumeDic) {
if (task.originalRequest == nil) {
NSData *originalReqData = resumeDic[kResumeOriginalRequest];
NSURLRequest *originalRequest = [NSKeyedUnarchiver unarchiveObjectWithData:originalReqData ];
if (originalRequest) {
[task setValue:originalRequest forKey:#"originalRequest"];
}
}
if (task.currentRequest == nil) {
NSData *currentReqData = resumeDic[kResumeCurrentRequest];
NSURLRequest *currentRequest = [NSKeyedUnarchiver unarchiveObjectWithData:currentReqData];
if (currentRequest) {
[task setValue:currentRequest forKey:#"currentRequest"];
}
}
}
return task;
}
#end

IOS: how to join 2 Dictionaries into 1 dictionary??

in my project i applied the following code
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSLog(#" for ref id =%# ,name of diagnose=%# data is= %#",refidstr,diagnosedictforname ,diagnosisdict);
and the output in console is comes out as in the form
str : {
diagnoses = (
{
Diagnoses = {
"diagnosis_name" = "TRANSIENT ISCHEMIA";
};
DiagnosesHospitals = {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
};
}
);
response = 200;
}
ref id =3341 ,name of diagnose={
"diagnosis_name" = "TRANSIENT ISCHEMIA";
} data is= {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
}
now i just want to embed the values of both the Dictionaries into one dictionary
someone please help me to sort out this issue.
Make a mutable copy of the first dictionary:
NSMutableDictionary * mutDic = [dic1 mutableCopy];
and then:
[mutDic addEntriesFromDictionary:dic2];
Try this code:
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
NSMutableDictionary *diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
NSDictionary *diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSArray *keys = [diagnosedictforname allKeys];
for (int i =0; i < keys.count; i++) {
NSString *key = [keys objectAtIndex:i];
[diagnosisdict setValue:[diagnosedictforname valueForKey:key] forKey:key];
}
NSLog(#"your dic -> %#", diagnosisdict);

Not able to print my json data in my console?

here is my code. I used NSDictionary and coded to print my json data in my console.but i got error like this:
'NSInvalidArgumentException', reason: '-[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7c971930'
My code:
if(buttonIndex == 0) {
NSLog(#"OK Button is clicked");
}
else if(buttonIndex == 1) {
if([[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]!=0)
{
if(!self.note)
{
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newNote = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:context];
NSLog(#"%#",textView.text);
[newNote setValue:textView.text forKey:#"note"];
if([textView.text length]>30)
{
[newNote setValue:[NSString stringWithFormat:#"%#...",[textView.text substringToIndex:25]] forKey:#"title"];
}
else
[newNote setValue:textView.text forKey:#"title"];
[newNote setValue:[NSDate date] forKey:#"mod_time"];
//[newDevice setValue:self.versionTextField.text forKey:#"version"];
//[newDevice setValue:self.companyTextField.text forKey:#"company"];
How to overcome this problem to work and to print my data in my console
Help me out. I am struggling for 2 hours.I googled and change all change.But cant get data in my console. Thanks in advance
I guess you can get data like below this
NSDictionary *monday = jsonResults[#"original"];
NSArray * arrFile = monday[#"files"];
for (NSDictionary *theCourse in arrFile)
{
....
}
Did you checked that received data (i.e., returnData) from sendSynchronousRequest: is returning a plain data?
If the data received is in Base64, you might have to decode this NSData to plain data, and then go ahead with String conversion.
NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:responseData options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSString *str = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
// convert Json to NSDictionary
NSDictionary *jsonResults = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];
// NSLog(#"%#",jsonResults);
int count = [[jsonResults valueForKey:#"count"] intValue];
NSArray *arrayData = [jsonResults copy];
NSMutableArray *arrayPDFName = [[NSMutableArray alloc]init];
for(int i = 0;i < [arrayData count];i++)
{
NSDictionary *dictOriginal = [[arrayData objectAtIndex:2]valueForKey:#"original"];
int countOriginal = [[dictOriginal valueForKey:#"count"] intValue];
NSLog(#"The countOriginal is - %d",countOriginal);
NSArray *arrayFiles = [[dictOriginal valueForKey:#"files"] copy];
NSLog(#"The arrayFiles are - %#",arrayFiles);
for(int j=0;j<[arrayFiles count];j++)
{
NSString *strCreatedTime = [NSString stringWithFormat:#"%#",[[arrayFiles objectAtIndex:j] valueForKey:#"created_time"]];
NSString *strLastModifiedTime = [NSString stringWithFormat:#"%#",[[arrayFiles objectAtIndex:j] valueForKey:#"last_modified_time"]];
NSString *strID = [NSString stringWithFormat:#"%#",[[arrayFiles objectAtIndex:j] valueForKey:#"id"]];
NSString *strName = [NSString stringWithFormat:#"%#",[[arrayFiles objectAtIndex:j] valueForKey:#"name"]];
NSLog(#"The created_time is - %#",strCreatedTime);
NSLog(#"The last_modified_time is - %#",strLastModifiedTime);
NSLog(#"The is is - %#",strID);
NSLog(#"The name is - %#",strName);
[arrayPDFName addObject:strName];
}
}

Is there a way to normalize json data from NSJSONSerialization?

It seems that since XCode 6.1, the iPhone 5S, iPhone 6 and iPhone 6+ simulators (all 64-bit) all return data from the following system method differently (keys are ordered differently) than their 32-bit simulator counterparts (e.g. iPhone 5 simulator)
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
This difference of key ordering caused a problem for me since we calculate the SHA1 of that JSON data (converted to NSString*) and use it for a validation test. Since the ordering changed, the SHA1 changed and the validation fails.
Simplified sample code (non-ARC) to get the SHA1 is below:
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:0
error:&error];
NSString * json = [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease];
NSString * sha1 = [MyUtils computeSHA1:json];
+(NSString*) computeSHA1:(NSString*)input
{
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
NSNumber* dataLen = [NSNumber numberWithUnsignedInteger:data.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, dataLen.unsignedIntValue, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
Apparently, this key ordering difference doesn't happen on the actual devices (previous behavior was preserved).
I also tried with the NSJSONWritingPrettyPrinted option but the JSON ordering is still inconsistent between simulators.
So, the question is: Does anyone have a recommendation on how to normalize such JSON data so as to not be susceptible to key ordering changes? Alternately, is there any way to get the previous (32-bit simulator) behavior?
Key ordering in dictionaries is not guaranteed. If you need them sorted, put them into an array and sort them.
The code below (non-ARC) worked for me to better canonicalize JSON output. The code assumes the class methods below are all in a class called MyUtils.
Simply pass the the NSDictionary to serialize into "canonicalized JSON" to canonicalJSONRepresentationWithDictionary:
The returned NSString* then contains serialized JSON that has the keys ordered lexicographically/alphabetically in a non-human readable format.
+(NSString *) canonicalJSONRepresentationWithDictionary:(NSDictionary *)dict
{
NSMutableString* json = [NSMutableString string];
[json appendString:#"{"];
NSArray* keys = [[dict allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString* a, NSString* b) {
return [a compare:b];
}];
for (int i = 0; i < keys.count; i++) {
NSString* key = keys[i];
[json appendFormat:#"\"%#\":", key];
if ([dict[key] isKindOfClass:[NSString class]]) {
[json appendFormat:#"\"%#\"", [MyUtils canonicalJSONRepresentationWithString:dict[key]]];
} else if ([dict[key] isKindOfClass:[NSDictionary class]]) {
[json appendString:[MyUtils canonicalJSONRepresentationWithDictionary:dict[key]]];
} else if ([dict[key] isKindOfClass:[NSArray class]]) {
[json appendString:[MyUtils canonicalJSONRepresentationWithArray:dict[key]]];
} else {
return nil;
}
if (i < keys.count - 1) {
[json appendString:#","];
}
}
[json appendString:#"}"];
return json;
}
+(NSString *) canonicalJSONRepresentationWithArray:(NSArray *) array
{
NSMutableString* json = [NSMutableString string];
[json appendString:#"["];
for (int i = 0; i < array.count; i++) {
if ([array[i] isKindOfClass:[NSString class]]) {
[json appendFormat:#"\"%#\"", [MyUtils canonicalJSONRepresentationWithString:array[i]]];
} else if ([array[i] isKindOfClass:[NSDictionary class]]) {
[json appendString:[MyUtils canonicalJSONRepresentationWithDictionary:array[i]]];
} else if ([array[i] isKindOfClass:[NSArray class]]) {
[json appendString:[MyUtils canonicalJSONRepresentationWithArray:array[i]]];
} else {
return nil;
}
if (i < array.count - 1) {
[json appendString:#","];
}
}
[json appendString:#"]"];
return json;
}
+(NSString *) canonicalJSONRepresentationWithString:(NSString *) string;
{
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:string, #"a", nil];
NSError * error;
NSData * jsonData = nil;
NSString * json = nil;
jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:0
error:&error];
if (!jsonData) {
NSLog(#"Got an error serializing json: %#", error);
return nil;
} else {
json = [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease];
}
NSRange colonQuote = [json rangeOfString:#":\""];
NSRange lastQuote = [json rangeOfString:#"\"" options:NSBackwardsSearch];
NSRange range = NSMakeRange(colonQuote.location + 2, lastQuote.location - colonQuote.location - 2);
NSString* rc = [json substringWithRange:range];
return rc;
}

How do I convert an LDAP "jpegPhoto" to NSString to UIImageView

I am trying to pull an LDAP "jpegPhoto" attribute from an openLDAP server using a iOS openLDAP framework. The framework pulls the data as a dictionary of NSStrings.
I need to convert the NSString of "jpegPhoto" (which also appears to be base64 encoded) to UIImage, with the end result being that I display the jpegPhoto as the user's image when they login.
More Info:
-(NSDictionary *)doQuery:(NSString *)query:(NSArray *)attrsToReturn {
...
while(attribute){
if ((vals = ldap_get_values_len(ld, entry, attribute))){
for(int i = 0; vals[i]; i++){
//Uncomment if you want to see all the values.
//NSLog(#"%s: %s", attribute, vals[i]->bv_val);
if ([resultSet objectForKey:[NSString stringWithFormat:#"%s",attribute]] == nil){
[resultSet setObject:[NSArray arrayWithObject:[NSString stringWithFormat:#"%s",vals[i]->bv_val]] forKey:[NSString stringWithFormat:#"%s",attribute]];
}else{
NSMutableArray *array = [[resultSet objectForKey:[NSString stringWithFormat:#"%s",attribute]] mutableCopy];
[array addObject:[NSString stringWithFormat:#"%s",vals[i]->bv_val]];
[resultSet setObject:array forKey:[NSString stringWithFormat:#"%s",attribute]];
}
}
ldap_value_free_len(vals);
};
ldap_memfree(attribute);
attribute = ldap_next_attribute(ld, entry, ber);
};
...
}
-(UIIMage *)getPhoto{
NSString *query = [NSString stringWithFormat:#"(uid=%#)",self.bindUsername];
NSArray *attrsToReturn = [NSArray arrayWithObjects:#"cn",#"jpegPhoto", nil];
NSDictionary *rs = [self doQuery:query:attrsToReturn];
NSString *photoString = [[rs objectForKey:#"jpegPhoto"] objectAtIndex:0];
NSLog(#"The photoString is: %i %#",[photoString length],#"characters long"); //returns 4
NSData *photoData = [NSData dataWithBase64EncodedString:photoString];
UIImage *userPhoto = [UIImage imageWithData:photoData];
return userPhoto;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.studentNameLabel.text = [NSString stringWithFormat:#"Hi %#!",[self.ldap getFullName]];
self.studentPhotoImage.image = [self.ldap getPhoto];
[self checkForProctor];
}
Try this code
NSData *dataObj = [NSData dataWithBase64EncodedString:beforeStringImage];
UIImage *beforeImage = [UIImage imageWithData:dataObj];
There are many similar questions in Stackoverflow.. Please refer the following links
UIImage to base64 String Encoding
UIImage from bytes held in NSString
(Since there has been no working code posted for getting the image data from LDAP, I wanted to add this answer for the benefit of future visitors.)
The missing piece was reading the binary data into an NSData object rather than an NSString when you have binary data that might contain NULL (zero) values within it, such as images or GUIDs.
value = [NSData dataWithBytes:vals[0]->bv_val length:vals[0]->bv_len];
+ (NSArray *)searchWithBaseDN:(const char *)baseDN andFilter:(const char *)filter andScope:(int)scope {
...
while(entry)
{
// create a dictionary to hold attributes
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
attribute = ldap_first_attribute(ld, entry, &ber);
while(attribute)
{
if ((vals = ldap_get_values_len(ld, entry, attribute)))
{
if (ldap_count_values_len(vals) > 1) {
NSMutableArray *values = [[NSMutableArray alloc] init];
for(int i = 0; vals[i]; i++) {
[values addObject:[NSString stringWithUTF8String:vals[i]->bv_val]];
}
[dictionary setObject:values forKey:[NSString stringWithUTF8String:attribute]];
} else {
NSObject *value = nil;
if (strcmp(attribute, "thumbnailPhoto") == 0 || strcmp(attribute, "objectGUID") == 0) {
value = [NSData dataWithBytes:vals[0]->bv_val length:vals[0]->bv_len];
} else {
value = [NSString stringWithFormat:#"%s", vals[0]->bv_val];
}
[dictionary setObject:value forKey:[NSString stringWithUTF8String:attribute]];
}
ldap_value_free_len(vals);
};
ldap_memfree(attribute);
attribute = ldap_next_attribute(ld, entry, ber);
};
...
}

Resources