There are lots of answers on SO that show devs how to make a string from HTML content or place a URL in a string, but my question is how to make an HTML string.
I'm trying to create a string that will return in HTML format or at least not show the URL.
So for example web devs would do this to hide the URL:
Visit Us at Google.com!
I can easily translate that to a string by doing so:
NSString *urlLink = #"www.google.com";
NSString *string = [NSString stringWithFormat:#"Visit Us at %#", urlLink];
But that doesn't replace the link with a hyperlink word of my choosing.
I'm aware that the device dictates if its a hyperlink depending on how you display it. i.e., text fields, text views, or you can force open it etc.
What i'm trying to do is:
#define APPSTORELINK #"www.appstorelink.com"
#implementation Config
+(NSString *)appstorelink {
return APPSTORELINK;
}
+(NSString *)mmsmetadata {
NSString *string = [NSString stringWithFormat:#"I shared this publication with the [Name of my iPhone App] iPhone App", APPSTORELINK];
return string;
}
So I can easily call it here or app wide:
NSArray *shareItems;
UIImage *snapshot = [self imageFromView:self.view];
shareItems = #[[Config mmsmetadata], snapshot];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:shareItems applicationActivities:nil];
activityController.excludedActivityTypes = #[UIActivityTypePostToFlickr, UIActivityTypeAssignToContact, UIActivityTypeMail, UIActivityTypePostToVimeo];
[activityController setCompletionWithItemsHandler:(UIActivityViewControllerCompletionWithItemsHandler)^(NSString *string, BOOL completed) {
So in short, how can I make the string HTML format out of the box? My main concern is I want to hide the URL and replace it with an HTML tag, or otherwise if you have a better solution. Can't find anything on SO.
Any thoughts? I'm probably overthinking this. I'm sure theres an easier way
EDIT
Before even posting I have been aware of NSAttributedString and that was the first thing I attempted. However, the issue isn't setting an attribute, thats the easy part, the part that is defining my question is how to set it so it will DISPLAY as attributed when using activities in the UIActivityViewController
Here is how I set it, but the outcome was the same as above so I figured it would be easier to use an HTML tag:
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"I shared this publication with the Army Pubs iPhone App!"];
NSRange selectedRange = NSMakeRange(0, [string length]);
NSURL *linkURL = [NSURL URLWithString:APPSTORELINK];
[string beginEditing];
[string addAttribute:NSLinkAttributeName
value:linkURL
range:selectedRange];
[string addAttribute:NSForegroundColorAttributeName
value:[UIColor blueColor]
range:selectedRange];
[string addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:selectedRange];
[string endEditing];
return string;
However, it still displays as plain text in the Message or Mail composers. So think MFMailComposeViewControllerDelegate how there is a setting for isHTML. If it's set to yes it strips all the HTML tags and displays the text as a hyperlink. For example:
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:YES];
I want to emulate that when the activities are called from within a UIActivityViewController
This is the output currently even if I do it with the attributed string I tried first it just displays as plain text by stripping the HTML tag but doesn't make it a link
See link option in attributed strings.
The link attribute specifies an arbitrary object that is passed to the NSTextView method
clickedOnLink:atIndex: when the user clicks in the text range
associated with the NSLinkAttributeName attribute. The text view’s
delegate object can implement textView:clickedOnLink:atIndex: or
textView:clickedOnLink: to process the link object. Otherwise, the
default implementation checks whether the link object is an NSURL
object and, if so, opens it in the URL’s default application.
Related
Can you show a html <img src=''> inside a NSAttributedString used in an UILabel?
Yes you can, even though Apple doesn't recommended it:
The HTML importer should not be called from a background thread (that is, the options dictionary includes documentType with a value of html). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import.
An UILabel's attributedText can be used to render html img tags.
Here an example:
let str = "<img src='https://www.codeterritory.com/assets/screenshot_sidiusnova_04-f5422e9916fb114e73484758278c284e.jpg'>"
let data = str.data(using: String.Encoding.unicode)!
do {
let attrStr = try NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType:NSAttributedString.DocumentType.html], documentAttributes: nil)
let label = UILabel(frame: UIScreen.main.bounds)
label.attributedText = attrStr
UIApplication.shared.windows.first!.addSubview(label)
} catch let error {
print(error)
}
I have a text in HTML format. I am using the property of NSAttributed string to parse it. It pareses the text nicely and displays on the label. However, the parsing of the anchor tag doesn't make the link clickable. This is the following code that I am using for parsing.
extension String {
var htmlToAttributedString: NSAttributedString? {
guard let data = data(using: .utf8) else { return NSAttributedString() }
do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch {
return NSAttributedString()
}
}
var htmlToString: String {
return htmlToAttributedString?.string ?? ""
}
When I run the app and give the value to the label as:
text = "<p>This is Google Home</p>"
simpleTextLabel.attributedText = text.htmlToAttributedString
The output on the iOS App looks like following but nothing happens on clicking :
This is Google Home.
How can I make it open in safari?
From your line:
simpleTextLabel.attributedText = text.htmlToAttributedString
We can assume that simpleTextLabel is a UILabel.
It's basic behavior from a UILabel to not be "interactable". You can add a tap gesture on it, but it transform it as a UIButton.
There are some tricks to make it possible with a UILabel, find where exactly it has been tapped, check if there is a link, etc.
Looking for "UILabel Clickable": Create tap-able "links" in the NSAttributedString of a UILabel? etc. There are even a few third party libs.
I (in my humble opinion) consider it as a "hack".
There is a good WWDC 2018 Session: TextKit Best Practices. At 2:34, it explains that if you need to interact with a shown text, prefers UITextView over UILabel.
There is a UITextViewDelegate method just for that: textView(_:shouldInteractWith:in:interaction:)
Note that there a small differences in the rendering of a UITextView and a UILabel. If you superpose them, they won't have the same "start point", the layout is a little different. However, with small changes, it can be the same (for instance: How can I make a UITextView layout text the same as a UILabel?).
Note also that according to the small modifications of a UITextView into a UILabel visual rendering, the user won't notice the difference (and that's in fact what matters, beside that using native methods of the UITextView/UITextViewDelegate make it easily understandable afterwards by another developer, or in a few months if you need to do a small modification).
I am trying to obtain the data within the header of a web page that is being displayed in a UIWebView.
How do I get the raw (unformatted) HTML string from the UIWebView?
Also, I'm using iOS 9.
My question is similar to Reading HTML content from a UIWebView , but this post is from 6 years ago.
From the top answer on the question you linked:
NSString *html = [yourWebView stringByEvaluatingJavaScriptFromString:
#"document.body.innerHTML"];
would translate into Swift:
let html = yourWebView.stringByEvaluatingJavaScriptFromString("document.body.innerHTML")
stringByEvaluatingJavaScriptFromString returns a optional, so you'd probably want to later use an if let statement:
if let page = html {
// Do stuff with the now unwrapped "page" string
}
swift 4:
if let html = self.webView.stringByEvaluatingJavaScript(from: "document.body.innerHTML"){
}
Don't forgot get the html when the page render finished, if you got html too early, the result will be empty.
func webViewDidFinishLoad(webView: UIWebView) {
print("pageDidFinished")
if let html = webView.stringByEvaluatingJavaScriptFromString("document.documentElement.outerHTML") {
print("html=[\(html)]")
}
}
I am trying to create an iOS app simply to extract the section of a web page.
I have the code working to connect to the URL and store the HTML in an NSString
I have tried this, but I am just getting null strings for my result
NSScanner* newScanner = [NSScanner scannerWithString:htmlData];
// Create a new scanner and give it the html data to parse.
while (![newScanner isAtEnd])
{
[newScanner scanUpToString:#"<body>" intoString:NULL];
// Scam until <body> tag is found
[newScanner scanUpToString:#"</body>" intoString:&bodyText];
// Everything up to the end tag will get placed into the memory address of the result string
}
I have tried an alternative way...
NSScanner* newScanner = [NSScanner scannerWithString:htmlData];
// Create a new scanner and give it the html data to parse.
while (![newScanner isAtEnd])
{
[newScanner scanUpToString:#"<body" intoString:NULL];
// Scam until <body> tag is found
[newScanner scanUpToString:#">" intoString:NULL];
// Go to end of opening <body> tag
[newScanner scanUpToString:#"</body>" intoString:&bodyText];
// Everything up to the end tag will get placed into the memory address of the result string
}
This second way returns a string which starts with >< script... etc
If Im honest I don't have a good URL to test this with and I think It may be easier with some help on removing the tags within the body too (like <p></p>)
Any help would be very much appriciated
I don't know why your first method didn't work. I assume you defined bodyText before that snippet. This code worked fine for me,
- (void)viewDidLoad {
[super viewDidLoad];
NSString *htmlData = #"This is some stuff before <body> this is the body </body> with some more stuff";
NSScanner* newScanner = [NSScanner scannerWithString:htmlData];
NSString *bodyText;
while (![newScanner isAtEnd]) {
[newScanner scanUpToString:#"<body>" intoString:NULL];
[newScanner scanString:#"<body>" intoString:NULL];
[newScanner scanUpToString:#"</body>" intoString:&bodyText];
}
NSLog(#"%#",bodyText); // 2015-01-28 15:58:00.360 ScanningOfHTMLProblem[1373:661934] this is the body
}
Notice that I added a call to scanString:intoString: to get past the first "<body>".
I'm writing on objective-C.
I have WebView and local file index.html has
<a href='http://www.google.com' name="666">
How can I get the name attribute?
Thanks!
It depends on when/by what you need to get the name. If you need the name when someone clicks on the link, you can set up some JavaScript that runs when the link is clicked (onclick handler). If you just have the html string, you can use regular expressions to parse the document and pull out all of the name attributes. A good regular expression library for Objective-C is RegexKit (or RegexKitLite on the same page).
The regular expression for parsing the name attribute out of a link would look something like this:
/<a[^>]+?name="?([^" >]*)"?>/i
EDIT: The javascript for getting a name out of a link when someone clicked it would look something like this:
function getNameAttribute(element) {
alert(element.name); //Or do something else with the name, `element.name` contains the value of the name attribute.
}
This would be called from the onclick handler, something like:
My Link
If you need to get the name back to your Objective-C code, you could write your onclick function to append the name attribute to the url in the form of a hashtag, and then trap the request and parse it in your UIWebView delegate's -webView:shouldStartLoadWithRequest:navigationType: method. That would go something like this:
function getNameAttribute(element) {
element.href += '#'+element.name;
}
//Then in your delegate's .m file
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSArray *urlParts = [[request URL] componentsSeparatedByString:#"#"];
NSString *url = [urlParts objectAtIndex:0];
NSString *name = [urlParts lastObject];
if([url isEqualToString:#"http://www.google.com/"]){
//Do something with `name`
}
return FALSE; //Or TRUE if you want to follow the link
}