iOS 7 allows an NSAttributedString to be initialized with an HTML file or data. I want to use this functionality to make it easier to insert links in 'About' texts of apps.
To achieve this, I initialize the NSAttributedString with the following code:
NSURL *url = [[NSBundle mainBundle] URLForResource:#"test.html" withExtension:nil];
NSError *error = nil;
NSDictionary *options = nil;
NSDictionary *attributes = nil;
_textView.attributedText = [[NSAttributedString alloc] initWithFileURL:url options:options documentAttributes:&attributes error:&error];
and a file with the following content:
<html><body>
<p>This is a test link. It leads to StackOverflow.<p>
</body></html>
Update
The above HTML still had the escape marks from trying to use it in code as an NSString. Removing the escapes makes it work just fine. Also answered my own question below.
End update
This works fine, and gives a string with the url properly formatted and clickable. Clicking the link calls the UITextView's delegate -textView:shouldInteractWithURL:inRange: method. However, inspecting the URL parameter shows the URL actually has the following absolute string:
file:///%22http://www.google.com/%22
which obviously doesn't open the appropriate webpage. I don't find the documentation on NSAttributedText clear enough to determine why this happens.
Anyone know how I should initialize the NSAttributedString to generate the appropriate URL?
Try reading the HTML file into a NSString and then use:
NSString *path = [[NSBundle mainBundle] pathForResource:#"test.html" ofType:nil];
NSString *html = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
_textView.attributedText = [[NSAttributedString alloc] initWithHTML:html baseURL:nil options:options documentAttributes:&attributes];
At least this should work if it is similar with what happens in UIWebViews. The URL is resolved using the baseURL. It appears that in your code the source url is also used as baseURL. So I am passing a nil URL to prevent resolving against a local file URL.
The answer to this question is that the HTML file was invalid.
Having copy/pasted the html directly from a string defined in Objective-C, I forgot to remove the escapes before each quote. This of course translated directly to a file url instead of an HTML url. Removing the escape marks fixes this.
Related
I am developing ios application where I am waiting for response which should be uploaded image Url. I am converting NSData to NSString this way.
NSString* resultInString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
when I log resultInString, I get __NSCFString * #"\"http:\/\/em.avatars.s3.amazonaws.com\/avatarsd765c404-887c-4c0e-a08b-f7066ec9befe.png\"" 0x17777080
I have no idea how to validate this url to set UIImageview in my application. please give me a hint.
before say something about solution i think your getting url from NSData is incorrect.
The response seems to be JSON-encoded. So simply decode the response string using a JSON library (SBJson, JsonKit etc.)
or you can user correct encode for your NSData.
after all you can create a NSUrl from your string & if it's exist so it's valid.
i write a sample code for you
you should remove some charectar from your url by this way or like this
[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
and for validation
NSUrl * url = [[NSURL alloc] initWithString:urlString];
if(url){ //valid url
}
I am trying to read in arabic text that I have contained inside of a .doc file, and use it in my app. Unfortunately, the only way I am able to retrieve the text is if I convert the document into .txt file.
Here is the code I have:
NSError *error = nil;
NSString *path = #"MyArabicDocument";
NSString *root = [[NSBundle mainBundle]pathForResource:path ofType:#"doc"];
NSString *myFile = [NSString stringWithContentsOfFile:root encoding:NSUTF8StringEncoding error:&error];
NSLog(#"my file contents are: %#", myFile);
NSLog(#"error is: %#", error);
The output of my NSString object is (null), and the error I get is:
error is: Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x7aace470 {NSFilePath=/Users/MyName/Library/Developer/CoreSimulator/Devices/.../data/Containers/Bundle/Application/..MyApp.app/MyArabicDocument.doc}
If I convert my document into an .rtf format, then my output (after changing the extension in the above block of code) is the following:
my file contents are: {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\fnil\fcharset178 AlBayan;\f2\fnil\fcharset178 GeezaPro;
}
{\colortbl;\red255\green255\blue255;}
\vieww10800\viewh8400\viewkind0
\deftab709
\pard\pardeftab709\pardirnatural
\f0\fs46 \cf0 1
\f1 - \'de\'f3\'dc\'c7\'e1\'f3 \'c7\'c8\'fa\'dc\'e4\'f5 \'c2\'c8\'f3\'f8 \'e6\'f3\'c7\'d3\'fa\'e3\'f5\'dc\'e5\'f5 \'e3\'f5\'cd\'f3\'e3\'f3\'f8\'dc\'cf\'f5
\f0 ~~~
\f1 \'c7\'e1\'e1\'e5\'f3 \'dd\'f6\'dc\'ed \'df\'f5\'dc\'e1\'f6\'f8 \'c7\'e1\'c3\'f5\'e3\'f5\'dc\'e6\'d1\'f6 \'c3\'f3\'cd\'fa\'dc\'e3\'f3\'dc\'cf\'f5 \
...
If I try to use an NSAttributedString object instead of an NSString object, but I still get a (null) value for my NSAttributedString object:
NSDictionary *attrs = #{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType, NSWritingDirectionAttributeName:#[#(NSWritingDirectionRightToLeft | NSTextWritingDirectionOverride)]};
NSAttributedString *text = [[NSAttributedString alloc] initWithFileURL:[[NSBundle mainBundle] URLForResource:#"MyArabicDocument" withExtension:#"doc"] options:attrs documentAttributes:nil error:&error];
The reason why this is important is that while my arabic text does indeed appear in my UITextView in my app, the problem is that it's appearance is nowhere near as nice as in the original document, which is what I would like to maintain in my app. Is this not possible?
.doc file in question is in binary format. (probably compressed like .docx)
http://en.wikipedia.org/wiki/Doc_(computing)
So you cannot put it in NSString as is. But you can get NSData:
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyArabicDocument" ofType:#"doc"];
NSData *data = [NSData dataWithContentsOfFile:path];
Unfortunately you cannot make an NSAttributedString from .doc in iOS, but you can in OS X (in iOS there only four doc types supported)
NSError *attrError;
NSDictionary *options = #{NSDocumentTypeDocumentAttribute: NSDocFormatTextDocumentType};
NSAttributedString *content = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:&attrError];
Instead you may try to load your .doc file into WebView.
Using NSData:
[self.webView loadData:data MIMEType:#"application/msword" textEncodingName:#"UTF-8" baseURL:nil];
But I think better with NSURLRequest (since you don't nee to set up encoding there)
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
NOTE: Any method you choose very likely will BREAK your format, I mean rendered document will be corrupted. Instead I recommend to convert .doc to .pdf In this case it will be good-loking.
For example Dropbox app for iOS defenetly converts .doc/.docx to pdf and than presented to the user as PDF (Of course not telling that it is PDF indeed).
I think you have a encoding issue when reading a file,
Refer below link
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Strings/Articles/readingFiles.html
May be it solve your problem
Best of luck!
I am trying to open the following url in UIWebView but it fails to load whereas changing it to:
http://www.google.com
works fine.
The url that I want to load is:
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#%#%#%#",#"http://m.forrent.com/search.php?address=",[[bookListing objectForKey:#"Data"] objectForKey:#"zip"],#"&beds=&baths=&price_to=0#{\"lat\":\"0\",\"lon\":\"0\",\"distance\":\"25\",\"seed\":\"1622727896\",\"is_sort_default\":\"1\",\"sort_by\":\"\",\"page\":\"1\",\"startIndex\":\"0\",\"address\":\"",[[bookListing objectForKey:#"Data"] objectForKey:#"zip"],#"\",\"beds\":\"\",\"baths\":\"\",\"price_to\":\"0\"}"]]]];
UPDATE:
I have purposely escaped the double quotes otherwise it gives me an error.
I checked the url by opening in my browser (on laptop) and it works perfectly fine:
The url in browser:
http://m.forrent.com/search.php?address=92115&beds=&baths=&price_to=0#{%22lat%22:%220%22,%22lon%22:%220%22,%22distance%22:%2225%22,%22seed%22:%221622727896%22,%22is_sort_default%22:%221%22,%22sort_by%22:%22%22,%22page%22:%221%22,%22startIndex%22:%220%22,%22address%22:%2292115%22,%22beds%22:%22%22,%22baths%22:%22%22,%22price_to%22:%220%22}
Your line of code looks convoluted, but basically it is a very simple one.
You should breakup this code from a one liner to multiple lines that are more readable.
That will also allow you to log and check the URL you actually created, like so:
NSLog(#"My url: %#", urlString);
Update:
I see you added the full url. Webview indeed fails to load that url (UIWebkit error 101).
The part of the url that causes the problem is the '#' character and dictionary that follows in the params. You should url encode that part of the url.
Try this:
NSString *address = #"http://m.forrent.com/search.php?";
NSString *params1 = #"address=92115&beds=&baths=&price_to=0";
// URL encode the problematic part of the url.
NSString *params2 = #"#{%22lat%22:%220%22,%22lon%22:%220%22,%22distance%22:%2225%22,%22seed%22:%221622727896%22,%22is_sort_default%22:%221%22,%22sort_by%22:%22%22,%22page%22:%221%22,%22startIndex%22:%220%22,%22address%22:%2292115%22,%22beds%22:%22%22,%22baths%22:%22%22,%22price_to%22:%220%22}";
params2 = [self escape:params2];
// Build the url and loadRequest
NSString *urlString = [NSString stringWithFormat:#"%#%#%#",address,params1,params2];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
The escaping method I used:
- (NSString *)escape:(NSString *)text
{
return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)text, NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
}
I would try encoding all of the key/value items in your url. Specifically the curly braces ({}) and the hash (#) symbols may be causing a problem.
I got "hello world" text to print after I hardcoded some html right into my UIWebView functions, but now I am trying to move that HTML to a file elsewhere on the file system, and it isnt rendering.
Here is what I have:
- (void)viewDidAppear:(BOOL)animated
{
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"learn" ofType:#"html" inDirectory:#"src/html_files"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[theWebView loadHTMLString:htmlString baseURL:nil];
}
and my HTML file is in a directory that I made called src/html_files and the file is named learn.html
What am I doing incorrectly that the HTML is not rendering on the screen?
Thank you!
Ok, so Groups are just a construct in Xcode for keeping your app's resources organized. Although Xcode uses the little folder icon, it doesn't necessarily mean those are actually separate folders on the (Mac or iOS) filesystem.
But, it sounds like you have added that file as a bundle resource. That's what the code you posted looks like, too, but I had to ask, to be sure.
Most likely, the only thing wrong is that this:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"learn"
ofType:#"html"
inDirectory:#"src/html_files"];
should be this instead:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"learn"
ofType:#"html"];
From the Apple documentation for NSBundle,
+ (NSString *)pathForResource:(NSString *)name
ofType:(NSString *)extension
inDirectory:(NSString *)bundlePath
bundlePath
The path of a top-level bundle directory. This must be a valid path. For example, to
specify the bundle directory for a Mac app, you might specify the path /Applications/MyApp.app.
The bundlePath parameter is not meant to specify relative paths to your bundle resources. The version of pathForResource:ofType: that does not have a bundlePath parameter is almost always what you'll use. It will find the learn.html file wherever it lives, once your app is installed, and return the full path to that. You don't really have to worry about how it's nested. It's just a bundle resource.
Give that a try. As I suggested in my comment, though, I always recommend taking advantage of the error parameter for debugging:
NSError* error;
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error: &error];
if (error != nil) {
NSLog(#"Error with stringWithContentsOfFile: %#", [error localizedDescription]);
}
Is there a url (.txt) for the source code of each website?
If not, how can i get the source code of a webpage and be able to show it in a UITextView ?
You should be able to use something like this:
NSString *googleString = #"http://www.google.com";
NSURL *googleURL = [NSURL URLWithString:googleString];
NSError *error;
NSString *googlePage = [NSString stringWithContentsOfURL:googleURL
encoding:NSASCIIStringEncoding
error:&error];
This will put the contents of the google home page into googlePage and, if applicable, the error into error. If the page being loaded uses Unicode characters, try NSUTF8StringEncoding instead of NSASCIIStringEncoding.