iPhone: How to Display Text from UIWebView HTML Document in a UITextView - iphone

I have an RSS feed that gets arranged in a UITableView which lets the user select a story that loads in a UIWebView. However, I'd like to stop using the UIWebView and just use a UITextView or UILabel.
This png is what I am trying to do (just display the various text aspects of a news story):
I have tried using:
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.textContent"];
and assigning the string to a UILabel but it doesn't work from where I am implementing it in webViewDidFinishLoad (--is that not the proper place?). I get a blank textView and normal webView.
If I overlay a UITextView on top of a UIWebView on its own (that is, a webView that just loads one page), the code posted above works displays the text fine. The problem arises when I try to process the RSS feed .
I've been stuck wondering why this doesn't work as it should for a few days now. If you have a better, more efficient way of doing it then placing the code in webViewDidFinishLoad, please let me know! Does it go in my didSelectRowAtIndexPath?
Thank you very much in advance!

I think the you should first log the string returned by :
NSString *myText = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.textContent"];
... in the case of the RSS feed to make sure that you are getting something back. It's possible the RSS page doesn't have the same javascript components and that it returns an empty string.
Once you've confirmed that, then it becomes a simple matter of getting it to display properly in the text view.

If the NSString you want to display is not empty, try to do something like this in the webViewDidFinishLoad method:
[yourUILabel performSelectorOnMainThread:#selector(setText:) withObject:[NSString stringWithFormat:#"bla bla %#", #"more bla"] waitUntilDone:YES];
The main thread of an iphone app is responsible for drawing components, that is why your label doesn't show your text.
You could also try setting setNeedsDisplay: to true
Also, the UILabel will not preserve the HTML format. It will display it as just text.

You could try the following:
NSString *htmlContent = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerHTML;"];
NSString *htmlContent = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerHTML;"];
NSString *htmlContent = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerText;"];
You lose out on formatting information with the last line of code.

Related

UIWebView loading and general performance

I am using UIWebView to display textual content in my app (I store the content in local HTML files that I pack with the app). All together, I have three web views whose content I change dynamically based on user feedback.
Although some might argue that this is not the most accepted way, I find UIWebView very convenient to display formatted text, and modify that text using HTML if necessary. While this works 99% of the time, on occasion, I experience problems that generally fall into one of these categories:
Sometimes, the web view content loads slow and is late a second or so.
The content loads but is not showing. However, as long as, I touch the view (try to scroll or something) the content pops in.
A few times I received memory warnings (usually not long after the app's initial loading) that in no way affected the performance of my app. It logged the memory warning but the app worked like nothing happened.
This is the method I use to load content to my web views:
- (void)loadSimpleDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
Aside from this, the shouldStartLoadWithRequest delegate method is also implemented, always returning a YES.
My question is: Is there a way to improve the reliability/performance of my web views (in particular loading)? Is there something I have overlooked, did wrong, or do not know about?
Some additional info:
I am on iOS6 SDK, use ARC, and do everything programmatically (do not use IB or storyboard).
You have 2 options to check what's going on:
Implement webViewDidStartLoad & webViewDidFinishLoad delegate methods to check why the content isn't showing (may be the content isn't loaded yet).
read the html content to an NSString then use loadHTMLString:baseURL instead of using loadRequest and check if it loads faster.
Hope this could help.

How to show TXT or ASCII file into UIWebView correctly

I'm trying to show TXT file (ASCII) into UIVewView. For example, using the site www.partisani.net/35.txt in Safari on MacBook works fine, Safari on iPhone doesn't. Safari's iPhone shows the file with another layout. Could someone help me, please?
As far as I can tell, the layout of the file on the Mac vs iOS is exactly the same. Are you talking about text wrapping? You can see that on the Mac by resizing the browser.
If you want to handle the line length differently you'll need to do so by setting up scrolling.
UPDATE with more detail:
This "sort of" changes the original content :). Basically, you need to tweak both the contentSize of the webview and embed the text file in some boilerplate HTML to reflow the text rather than have the default viewport width assigned to the text document. The latter I accomplish with something like:
NSURL* url = [NSURL URLWithString:#"http://www.partisani.net/35.txt"];
UIWebView* vw = (UIWebView*)self.view;
vw.delegate = self;
NSData* Data = [NSData dataWithContentsOfURL:url];
NSString* aStr = [[NSString alloc] initWithData:Data encoding:NSASCIIStringEncoding];
NSString* responseStr = [NSString stringWithFormat:
#"<HTML>"
"<head>"
"<title>Text View</title>"
"</head>"
"<BODY>"
"<pre>"
"%#"
"/pre>"
"</BODY>"
"</HTML>",
aStr];
[vw loadHTMLString:responseStr baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
[aStr release];
The vw.delegate = self is important, as you also need to have your controller conform to the UIWebViewDelegate protocol and implement the webViewDidFinishLoad: method. There you can set the scroll width and height of your webview as needed:
- (void) webViewDidFinishLoad:(UIWebView *)webview {
UIScrollView* sview = (UIScrollView*)[[webview subviews] objectAtIndex:0];
sview.contentSize = CGSizeMake(1000, 800);
}
This is an extremely barebones implementation--presumably you would also want logic to calculate the necessary width and height based upon the loaded text rather than use constants as shown here; you'll need some parsing logic associated with the original data for that, but this should get you started.
Setting the scalesPageToFit property to yes might fix your problem.
I'm not sure this is actually something to do with TXT or ASCII, but rather the UIWebview resizing the content.
The file you mentioned loaded into a landscape ipad screen has exactly the same layout as on Mac Safari:
You can change whether or not the UIWebView scales its content with the scalesPageToFit property.

Is it possible to programmatically invoke "select all" then "copy" on a UIWebView on iPhone?

I want to provide a copy button where the user can quickly copy the text from a UIWebView. When I hold my finger and move it to the edges, I have no problem selecting all of the text, and then hitting copy. Is there a way to programmatically do this?
I didn't try it, but this should work to get the already selected text:
NSString *webViewString = [webView stringByEvaluatingJavaScriptFromString:#"(function (){return window.getSelection().toString();})();"];
[[UIPasteboard generalPasteboard] setString:webViewString]; //Copy to pasteboard
NSString *pasteBoardString = [[UIPasteboard generalPasteboard] string]; //Paste from pasteboard
Just search for another javascript snippet to select all... You should find one very quickly.
You can get the text in the UIWebView with some javascript:
NSString *innerText = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerHTML"];
It will give you the HTML text, including tags and everything...

how to insert UIImage into UITextView

im working on a editable notebook type project. it consists some text and images at any time.
in UITextView if we add images as subview the frames are fixed. but i have editable option. so i must save image as NSString format in UITextView, but it should look image type in uipart. so please suggest me how can i handle this requierment.
Thanks in advance
I think you're asking for something that's not possible.
If you need to truly interleave text and graphics, UIWebView is about your only answer. But it's not editable.
I know it's too late.
As per my understanding, you can use UIWebView to insert text and images both. Create an HTML file and put it in app bundle. Set the attribute of div or paragraph(in HTML) as contentEditable = "true". And load that file:-
NSBundle *bundle = [NSBundle mainBundle];
NSURL *indexFileURL = [bundle URLForResource:#"Index" withExtension:#"html"]; // HTML file name is "Index"
[YourWebView loadRequest:[NSURLRequest requestWithURL:indexFileURL]];
This way, your UIWebView becomes editable and you can insert text and image both. Edit:- Please have a look at this link:- Adding Images to UITextView
Solved as follows. Taken Scrollview, in that managing size of the textview & inserting image with Specified size. Like textview,image,tetxview, image and goes on...
Thanks for all your support to solve the issue.

How do I use a UIWebView in a Table Cell?

I'm building a table with some text that is HTML, so I am using a UIWebView as a subview of my custom table cells. I already ran into one problem - as I scrolled down in the table, it would take the UIWebViews a second to update. For example, I'd be viewing Cells at rows numbered 1, 2, and 3. I'd scroll down to say 8, 9, and 10. For a moment, the content of the UIWebView that was visible in cell #8 was the content from cell #1, the content in cell #9 was that from cell #2, and so on.
I learned that the problem was that UIWebViews simply render their text slowly. It was suggested to instead preload the content into the UIWebView as soon as I could instead of waiting until the table receives the cellForRowAtIndexPath. So now, I have a Domain Object which before just had the text content of the WebView - but now it actually has a reference to the UIWebView itself.
But now some of the content in the UIWebView renders, and when I scroll through the table the UIWebView shows only as a grey box. If I touch the grey box, it will actually receive the touch and update the WebView - for example if I touch a link (which I may or may not do, since the box is gray and it would be by a stroke of luck), the page that was linked to will be requested and displayed properly.
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// I suppose this isn't necessary since I am just getting it from the
// Domain Object anyway
content = [[UIWebView alloc] initWithFrame:CGRectZero];
content.backgroundColor = [UIColor blackColor];
[self addSubview:content];
[content release];
}
return self;
}
// called by cellForRowAtIndexPath
- (void)setMyDomainObject:(MyDomainObject*)anObject {
UIWebView *contentWebView = anObject.contentWebView;
int contentIndex = [self.subviews indexOfObject:content];
[self insertSubview:contentWebView atIndex:contentIndex];
}
One way to deal with this would be to use several UILabels, each with different fonts. Then strategically place them within the cell as to make them seem like contiguous text. I've seen this done in a UITableView with very good results.
Another performance problem may be that you are overiding UItableViewCell and it's init method. This almost always leads to poor performance in a UITableView. Instead just use the regular UITableViewCell instances and add subviews to it's contentView.
This has been covered extensively by Matt Gallagher's Easy Custom UITableView Drawing.
Another method described was to use Three20, which can give you styled text as well.
What you are attempting currently can't be done with UIWebview.
Preloading won't help: this would slow down the UI when UIWebviews are being rendered offscreen; you should always practice lazy loading on the iPhone.
Putting UIWebviews in a UITableView will come with a potentially unacceptable performance hit. You will need to use other means to accomplish your goal.
Unfortunately, NSAttributedString is unavailable in UIKit, which could easily solve your problem.
So here's my updated answer: I've implemented a table using one big UIWebView to put styled text inside table cells in my own Twitter client app, HelTweetica (with source available). It works pretty well as long as you understand how to do layout in HTML and CSS.
You just create a NSMutableString and add the lines of HTML that make up your document. You can references external files such as CSS files that are in your app's sandbox. You can set custom URL actions such as "youraction://file.txt" that your web view delegate can intercept and process as a replacement IBActions:
- (void) refreshWebView {
TwitterAccount *account = [twitter currentAccount];
NSMutableString *html = [[NSMutableString alloc] init];
// Open html and head tags
[html appendString:#"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"];
[html appendString:#"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"];
[html appendString:#"<head>\n"];
[html appendString:#"<meta name='viewport' content='width=device-width' />"];
[html appendString:#"<link href='style-ipad.css' rel='styleSheet' type='text/css' />"];
[html appendString:#"<script language='JavaScript' src='functions.js'></script>"];
// Body
[html appendString:#"</head><body><div class='artboard'>"];
// [...]
// Close artboard div, body. and html tags
[html appendString:#"</div></body></html>\n"];
NSURL *baseURL = [NSURL fileURLWithPath: [[NSBundle mainBundle] bundlePath]];
[self.webView loadHTMLString:html baseURL:baseURL];
[html release];
}
And you can reload parts of the page by using javascript:
- (void) refreshTabArea {
NSString *html = [self stringByEscapingQuotes: [self tabAreaHTML]];
NSString *js = [NSString stringWithFormat: #"document.getElementById(\"tab_area\").innerHTML = \"%#\";", html];
[self.webView stringByEvaluatingJavaScriptFromString:js];
}
If the content in the web view is restricted to styled text or hyperlinks you might want to take a look at the Three20 project: http://github.com/joehewitt/three20/tree/master
Its TTStyledText class has support for <b>, <i>, <img>, and <a> tags in the content. Probably more lightweight than webviews.
This isn't answering the original question asked, but taking one step back and looking at the bigger picture, if you're trying to display a hyperlink in a table cell, does that mean when you click on it it opens a web browser? Would it be the same if you showed styled text in the table cell that looks like or hints at a link, but open a separate screen with a full-screen web view that lets you tap on the link?
You said 'called by setRowAtIndexPath', you might mean 'cellForRowAtIndexPath' which is a UITableView method called when a row becomes visible and needs to create a cell. Make sure that in this method you are properly initializing and updating the cell contents.
Have you looked into overriding the -prepareForReuse method on your table cell subclass? If the cells don't seem to update when you scroll, it's possible that the content of reusable cells isn't being cleared and reset.
My understanding is that a WebView won't render unless you initiate the loading of it AFTER viewDidLoad() happens.