Is it possible to get only all the text content of the child elements recursively in hpple. Any method in TFHppleElement class?
such as the javascript
document.getElementById("testdiv").textContent
I'm using this code to get all content of the news title
NSURL *newURL = [NSURL URLWithString:#"http://somesite"];
NSData *newsData = [NSData dataWithContentsOfURL: newURL];
TFHpple *newsParser = [TFHpple hppleWithHTMLData: newsData];
NSString *newsXpathQueryString = #"//div[#class='item column-1']";
NSArray *newsNodes = [newsParser searchWithXPathQuery: newsXpathQueryString];
NSMutableArray *newNews = [[NSMutableArray alloc] initWithCapacity: 0];
for (TFHppleElement *element in newsNodes)
{
News *news = [[News alloc] init];
[newNews addObject: news];
news.title = [[element content] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
news.photo_url = [element objectForKey:#"src"];
_allNews = newNews;
[self.tableView reloadData];
}
}
you can use
news.title = [[element firstChild]content] to get children elements content
I wanted something like this - a quick boiler plate code, it is not an elegant solution with static contents. Please let me know, how can this be improved :)
#pragma mark - Hpple XML parser
/* The documents contents lots of nested div, table, span, style etc. */
- (NSString *) extractDefinition
{
NSString *html = [self.webView stringByEvaluatingJavaScriptFromString: #"document.getElementById('innerframe').innerHTML"];
if ([Resources stringIsEmpty:html]) {
return nil;
}
return [self extractSubDiv:html];
}
- (NSString *)extractSubDiv:(NSString *)html
{
TFHpple *hppleParser = [TFHpple hppleWithHTMLData:[html dataUsingEncoding:NSUTF8StringEncoding]];
NSString * xpathQuery;
xpathQuery = #"//div[#id='columnboth']";
NSArray * defNodes = [hppleParser searchWithXPathQuery:xpathQuery];
NSString * text = nil;
if ([defNodes count] > 0) {
TFHppleElement * element = [defNodes objectAtIndex:0];
text = [self parseContents:element];
} else {
xpathQuery = #"//div[#id='columnsingle']";
defNodes = [hppleParser searchWithXPathQuery:xpathQuery];
if ([defNodes count] > 0) {
TFHppleElement * element = [defNodes objectAtIndex:0];
text = [self parseContents:element];
}
}
return text;
}
- (NSString *) parseContents:(TFHppleElement *)element {
NSArray * innhold = [element searchWithXPathQuery:#"//div[contains(#class,'articlecontents')]"];
return [self getTextFromArray:innhold];
}
static NSMutableString * contents;
- (NSString *) getTextFromArray:(NSArray *)hppleElments {
NSMutableString * text = [[NSMutableString new] autorelease];
contents = nil;
contents = [[NSMutableString new] autorelease];
for (TFHppleElement * e in hppleElments) {
[text appendFormat:#"%# ", [self getText:e]];
}
return text;
}
/* Here are more nested div and then span for text. */
- (NSString *) getText:(TFHppleElement *)element
{
if ([element isTextNode]) {
[contents appendFormat:#" %#", element.content];
}
for (TFHppleElement * e in element.children) {
[self getText:e];
}
return contents;
}
Related
I am using SQLite and I want to save the name, address, and phone text fields for them to show up in the next view controller for when the "show details" button is clicked in 1st VC.
I placed "save" and "show details" button in 1st VC, as well as "previous" and "next" button in 2nd VC. Whenever I click on "show details" I am getting this error message:
index 0 beyond bounds for empty array.
However, I see that the array is not empty. I want to store the student details in the array.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *homeDirectory = NSHomeDirectory();
NSString *documentsDirectoryPath = [homeDirectory stringByAppendingPathComponent:#"Documents"];
self.dbFilePathInDocuments = [documentsDirectoryPath stringByAppendingPathComponent:#"details.db"];
self.studentDetails = [[NSMutableArray alloc]init];
NSString *selectQuery = [NSString stringWithFormat:#"select name,address,phone from contacts"];
sqlite3_open([self.dbFilePathInDocuments UTF8String], &dataBase);
sqlite3_prepare_v2(dataBase, [selectQuery UTF8String], -1,&selectStatement, NULL);
while (sqlite3_step(selectStatement) == SQLITE_ROW)
{
NSMutableDictionary *studentDict = [[NSMutableDictionary alloc]init];
NSString *name = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 0)];
NSString *address = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 1)];
NSString *phone = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 2)];
[studentDict setObject:name forKey:#"name"];
[studentDict setObject:address forKey:#"address"];
[studentDict setObject:phone forKey:#"phone"];
[self.studentDetails addObject:studentDict];
NSLog(#"student is:%#",self.studentDetails);
}
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
self.nameLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"phone"];
currentStudentIndex = 0;
}
- (IBAction)clickPrevious:(id)sender {
if(currentStudentIndex <=0)
{
currentStudentIndex = 0;
}else
{
currentStudentIndex = currentStudentIndex - 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
- (IBAction)clickNext:(id)sender {
if(currentStudentIndex >= [self.studentDetails count] - 1)
{
currentStudentIndex = [self.studentDetails count] - 1;
}else
{
currentStudentIndex = currentStudentIndex + 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
The issue is that you always accessing the array self.studentDetails even if it's empty. This will cause an exception.
First limit setting of the labels to a single method and check the array access will succeed before attempting it:
- (void)updateLabels
{
if (currentStudentIndex >= [self.studentDetails count])
return;
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
and use that method in the 3 places you currently set the labels. For example:
- (IBAction)clickPrevious:(id)sender {
currentStudentIndex--;
[self updateLabels];
}
- (IBAction)clickNext:(id)sender {
currentStudentIndex++;
[self updateLabels];
}
In the viewDidLoad method use this code:
...
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
currentStudentIndex = 0;
[self updateLabels];
After that you're gonna want to work on enabling/disabling buttons depending on whether there is a next or previous student to view to make using the app more intuitive.
I’m building an article reading app. I’m fetching data from JSON link like article image and title in uitableview.
I’m unable to implement pagination in uitableview, let say my JSON link is www.example.com&page=1 contain 10 articles at a time which is 1-10.
When I concatenate in the JSON link like www.example.com&page=2 to get 11-20 article list.
I’m unable to implement how I can load the data in uitableview on scrolling and increase no.of rows with data.
Here is my code:
int *x=1;
int *inc=10;
#interface ysTableViewController ()
{
Reachability *internetReachable;
}
#end
#implementation ysTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self checkInternetConnection];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20,10,0,20)];
titleLabel.textColor = [UIColor blackColor];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.text = #"Story";
[self.navigationItem setTitleView:titleLabel];
}
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 10;
if(y > h + reload_distance) {
NSLog(#"load more rows");
inc=inc+10;
BOOL myBool = [self isNetworkAvailable];
if (myBool)
{
#try {
// for table cell seperator line color
self.tableView.separatorColor = [UIColor colorWithRed:190/255.0 green:190/255.0 blue:190/255.0 alpha:1.0];
// for displaying the previous screen lable with back button in details view controller
UIBarButtonItem *backbutton1 = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backbutton1];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSString *urlString=[NSString stringWithFormat:#“www.example.com&page=%d",x];
NSLog(#"xxxxx===%d",x);
NSURL *newUrl=[NSURL URLWithString:urlString];
NSData* data = [NSData dataWithContentsOfURL:newUrl];
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
x++;
if(ys_avatars){
for (int j=0;j<ys_avatars.count;j++)
{
[_Title1 addObject:ys_avatars[j][#"title"]];
[_Author1 addObject: ys_avatars[j][#"author"]];
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
[_Details1 addObject:ys_avatars[j][#"content"]];
[_link1 addObject:ys_avatars[j][#"permalink"]];
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
} }
else
{
NSLog(#"asd");
} }
#catch (NSException *exception) {
}
}
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return inc;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Cellidentifier1 = #"ysTableViewCell";
ysTableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:Cellidentifier1 forIndexPath:indexPath];
// Configure the cell...
long row = [indexPath row];
cell1.TitleLabel1.text = _Title1[row];
cell1.AuthorLabel1.text = _Author1[row];
NSString *yourStoryUrl = [_Images1[indexPath.row] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
if(yourStoryUrl) {
NSArray *subStringsUrl = [yourStoryUrl componentsSeparatedByString:#"/"];
NSString *stripedName = [subStringsUrl lastObject];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//Local stored image file path
NSString* filePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#",stripedName]];
if(filePath) {
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
if(image) {
// Now the image will have been loaded and decoded and is ready to rock for the main thread
ysTableViewCell *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];
if(updateCell)
updateCell.ThumbImage1.image=image;
cell1.ThumbImage1.image=image;
} else {
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(taskQ, ^{
NSURL *Imageurl = [NSURL URLWithString:yourStoryUrl];
NSData *data = [NSData dataWithContentsOfURL:Imageurl];
UIImage *images1 = [[UIImage alloc] initWithData:data];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSData *imageData = UIImagePNGRepresentation(images1);
//_imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",stripedName]];
// NSLog((#"pre writing to file"));
if (![imageData writeToFile:filePath atomically:NO])
{
NSLog((#"Failed to cache image data to disk"));
}
else
{
NSLog((#"the cachedImagedPath is %#",filePath));
}
// Now the image will have been loaded and decoded and is ready to rock for the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
ysTableViewCell *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];
if(updateCell)
updateCell.ThumbImage1.image=images1;
cell1.ThumbImage1.image=images1;
});
});
}
} else {
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(taskQ, ^{
NSURL *Imageurl = [NSURL URLWithString:yourStoryUrl];
NSData *data = [NSData dataWithContentsOfURL:Imageurl];
UIImage *images1 = [[UIImage alloc] initWithData:data];
// NSString *myString = [Imageurl absoluteString];
// NSLog(#"%#",myString);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSData *imageData = UIImagePNGRepresentation(images1);
_imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",stripedName]];
// NSLog((#"pre writing to file"));
if (![imageData writeToFile:_imagePath atomically:NO])
{
NSLog((#"Failed to cache image data to disk"));
}
else
{
// NSLog((#"the cachedImagedPath is %#",_imagePath));
}
// Now the image will have been loaded and decoded and is ready to rock for the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
ysTableViewCell *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];
if(updateCell)
updateCell.ThumbImage1.image=images1;
cell1.ThumbImage1.image=images1;
});
});
}
}
return cell1;
}
This is by no means easy. IN GENERAL TERMS you need code that looks like this..
Note the four very distinct parts of this fundamental routine.
I have never found a working "general" package solution for this problem.
Again, look to the "four sections" in this: they give the logic you're looking for!
-(void)forTerm:(NSString *)term doPageAfter:(int)doingThisPage
{
doingThisPage = doingThisPage + 1;
if ( doingThisPage > 20 ) return; // never, ever, ever forget that!! heh.
[CLOUD search:term page:doingThisPage then:^(NSArray *thoseTenResults)
{
self.searchSpinner.hidden = YES;
// (step 1) IF IT IS "PAGE 1", we need to re-kick-off the array...
if ( doingThisPage == 1 )
CLOUD.searchResultsRA = [[NSMutableArray alloc] init];
// (step 2) go ahead and add on these results
if ( doingThisPage == 1 )
{
[CLOUD.searchResultsRA addObjectsFromArray:thoseTenResults];
[self.searchDisplay safelyReloadBouncyTable];
}
else
{
[self.searchDisplay.collectionView performBatchUpdates:^
{
NSUInteger oldSize = CLOUD.searchResultsRA.count;
[CLOUD.searchResultsRA addObjectsFromArray:thoseTenResults];
NSUInteger newSize = CLOUD.searchResultsRA.count;
NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
for (NSUInteger i = oldSize; i < newSize; i++)
[arrayWithIndexPaths
addObject:[NSIndexPath indexPathForRow:i inSection:0]];
[self.searchDisplay justSignal];
[self.searchDisplay.collectionView
insertItemsAtIndexPaths:arrayWithIndexPaths];
}
completion:nil];
}
// (step 3) indeed if it's the first page, do a drop-in for fun
if ( doingThisPage == 1 ) [self.searchDisplay.view dropIn:nil];
// (for a "new search" which is now being displayed, in your UX
// there would be some sort of indication of that fact - do it here)
// (step 4) IF there WERE results .. try another page!
if ( thoseTenResults.count > 0 )
[self forTerm:term doPageAfter:doingThisPage];
// note we are calling this same routine, again!!!
}
];
}
I have data exported to excel it works fine.
But I have a little question
My output is exported like this:
What i would like to happen is this:
and this is my code to export:
-(void)exportCSV {
NSArray * data = [NSArray arrayWithObjects:entries,keys, nil];
NSLog(#"%#",data);
csv =[NSMutableString string];
for (NSArray * line in data) {
NSMutableArray * formattedLine = [NSMutableArray array];
for ( field in line) {
BOOL shouldQuote = NO;
NSRange r = [field rangeOfString:#","];
//fields that contain a , must be quoted
if (r.location != NSNotFound) {
shouldQuote = YES;
}
r = [field rangeOfString:#"\""];
//fields that contain a " must have them escaped to "" and be quoted
if (r.location != NSNotFound) {
field = [field stringByReplacingOccurrencesOfString:#"\"" withString:#"\"\""];
shouldQuote = YES;
}
if (shouldQuote == YES) {
[formattedLine addObject:[NSString stringWithFormat:#"\"%#\"\"%#\"", entries,keys]];
} else {
[formattedLine addObject:field];
}
}
NSString * combinedLine = [formattedLine componentsJoinedByString:#";"];
[csv appendFormat:#"%#\n", combinedLine];
NSLog(#"%#",csv);
}
}
Does the following do what you want?
Note that I have not considered quotation, I leave that up to you ;)
Also note that I assume that entries.count == keys.count
- (void)exportCSV {
NSArray *keys = #[#"T", #"R", #"RTT"];
NSArray *entries = #[#"-329180696", #"1243918297", #"-998693494"];
NSMutableString *csv = [[NSMutableString alloc] initWithCapacity:0];
for (int i = 0; i < entries.count; i++) {
[csv appendFormat:#"%#;%#\n", keys[i], entries[i]];
}
}
Output:
T;-329180696
R;1243918297
RTT;-998693494
I'm using Hpple to parse HTML and it seems that it doesn't recognize it is actually XML, which it should (XCode debugger shows this variable isXML = (BOOL) NO and it doesn't collect any data). How do I fix this?
This is my code (they're may be other bugs as well). the parse method/function is called first with [ListParser parse:#"http://www.fanfiction.net/book/Harry-Potter/" at:#"//div[#=\"class\"]"];:
#interface ListParser () //private
+ (NSArray*) getNodeListAt: (NSURL*) page inside: (NSString*) page;
+ (NSDictionary*) getNodeData: (TFHppleElement*) node;
+ (void) addMiniListData: (NSString*) list to: (NSMutableDictionary*) dict;
#end
#implementation ListParser
+ (NSArray*) getNodeListAt: (NSURL*) page inside: (NSString*) path { // "//div[#class"z-list"]"
NSData *data = [NSData dataWithContentsOfURL: page];
TFHpple *listparser = [TFHpple hppleWithHTMLData:data]; //WHERE CODE SEEMS TO STOP TO WORK
NSArray *done = [listparser searchWithXPathQuery: path];
return done;
}
+ (void) addMiniListData: (NSString*) list to: (NSMutableDictionary*) dict{
NSArray *parts = [list componentsSeparatedByString:#" - "];
for(NSString* p in parts){
NSArray* two = [p componentsSeparatedByString:#": "];
[dict setObject:[two objectAtIndex:1] forKey:[two objectAtIndex:0]];
}
}
+ (NSDictionary*) getNodeData: (TFHppleElement*) node{
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[[[node firstChild] firstChild] objectForKey:#"href"] forKey:#"Image"];
[data setObject:[[node firstChild] text] forKey:#"Title"];
[data setObject:[[[[node firstChild] children] objectAtIndex:2] text] forKey:#"By"];
[data setObject:[[[[node firstChild] childrenWithClassName:#"z-indent"] objectAtIndex:0] text] forKey:#"Summery"];
[self addMiniListData:[[[[[[node firstChild] childrenWithClassName:#"z-indent"] objectAtIndex:0] childrenWithClassName:#"z-padtop2"] objectAtIndex:0] text] to: data];
return data;
}
+(NSArray*) parse: (NSString*) address at: (NSString*) path{
NSURL *url = [[NSURL alloc] initWithString:address];
NSArray* list = [self getNodeListAt:url inside:path];
NSMutableArray *data = [[NSMutableArray alloc] init];
for (TFHppleElement* e in list) {
[data addObject:[self getNodeData:e]];
}
return [[NSArray alloc] initWithArray: data];
}
#end
Here's a link to the tutorials I was following: http://www.raywenderlich.com/14172/how-to-parse-html-on-ios
If you need to parse XML with a TFHpple, you should tell it that you're doing so. You're calling +hppleWithHTMLData:. If you read the implementation of this method, you will see that it sets isXML to NO. Instead, use the hppleWithXMLData: method.
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);
};
...
}