HTML in textview - cocoa

I am using textview in cocoa
How we show a HTML data in textview

You didn't say if you're targeting the Mac or the iPhone. I'll assume the Mac since you tagged your question with cocoa.
It would be worth looking into the Text System documentation for an overview of how NSTextView works. But at a basic level, all NSTextViews have an NSTextStorage object (accessible via the textStorage method) NSTextStorage happens to be a subclass of NSMutableAttributedString.
NSAttributedString has an initializer called initWithHTML:baseURL:documentAttributes: which will parse an HTML string for you. Once you've got that, you can append the resulting string to your NSTextView's textStorage. For example:
NSData *htmlData = // get the html, e.g. from a file
NSURL *aBaseURL = // a URL used to resolve relative links e.g. '/directory/page.html'
NSAttributedString *formattedHTML = [[NSAttributedString alloc] initWithHTML:htmlData baseURL:aBaseURL documentAttributes:NULL];
[[myTextView textStorage] appendAttributedString:formattedHTML];
[formattedHTML release];

You can use an UIWebView and fill it with a string instead of a webpage.

Why not use a WebView (part of the WebKit framework)? Although NSTextView has rudimentary HTML support, WebView gives you all of the power of the modern, standards-compliant, WebKit framework.

If macOS NSTextView
Swift 5:
let data = htmlString.data(using: .utf8)!
if let attributedString = NSAttributedString(html: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
{
textView.textStorage?.append(attributedString)
textView.textColor = .labelColor
textView.font = NSFont.systemFont(ofSize: 15)
}

Related

Transparent background WKWebView (NSView)

I am building a Mac application using Swift. Therefor, I want to make a WKWebView transparent, so it shows the text of the loaded HTML, but the background of my underlaying NSWindow is visible.
I tried
webView.layer?.backgroundColor = NSColor.clearColor().CGColor;
which hadn't any effect. WKWebView inherits from NSView, but I don't know if this helps.
Another solution would be to insert a NSVisualEffectView as the background of the WebView, but I don't know how to accomplish that, either!
Use this in macOS 10.12 and higher:
webView.setValue(false, forKey: "drawsBackground")
It was not supported, then they fixed it:
https://bugs.webkit.org/show_bug.cgi?id=134779
The way to make it transparent is to:
myWebView.opaque = false
Code below works for me perfectly, also color is set to clearColor by default.
[wkWebView setValue:YES forKey:#"drawsTransparentBackground"];
I used this for macOS 10.12. without problems in OjbC:
[self.webView setValue:#YES forKey:#"drawsTransparentBackground"];
Under macOS 10.13.+ I got the following console warning message:
-[WKWebView _setDrawsTransparentBackground:] is deprecated and should not be used
The ONLY working solution was:
[self.webView setValue:#(NO) forKey:#"drawsBackground"];
I tried the below in many scenarios and it didn't work:
give the webView and the enclosingScrollView a layer and edit it's properties (backgroundColor, isOpaque)
give the webView and the enclosingScrollView a clear background color
inject javascript without the setValue forKey: in the webview.
Additionally I did use:
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
if (self.isWebviewsBackgroundTransparent) {
[self insertTransparentBackgroundTo:webView];
}
}
- (void)insertTransparentBackgroundTo:(WKWebView *)webView
{
NSString *transparentBackgroundJSSString = #"document.body.style = document.body.style.cssText + \";background: transparent !important;\";";
[webView evaluateJavaScript:transparentBackgroundJSSString completionHandler:nil];
}
Updated, slightly better solution (2022). There is a private property drawsBackground on WKWebViewConfiguration. This property has been introduced in macOS 10.14 so it won't go away.
//https://opensource.apple.com/source/WebKit2/WebKit2-7610.2.11.51.8/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h.auto.html
//One can verify that the property still exists:
//https://github.com/WebKit/WebKit/blob/main/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
#property (nonatomic, setter=_setDrawsBackground:) BOOL _drawsBackground WK_API_AVAILABLE(macos(10.14), ios(12.0));
Example:
let configuration = WKWebViewConfiguration()
var requiresDrawBackgroundFallback = false
if #available(OSX 10.14, *) {
configuration.setValue(false, forKey: "sward".reversed() + "background".capitalized) //drawsBackground KVC hack; works but private
} else {
requiresDrawBackgroundFallback = true
}
let webView = WKWebView(frame: .zero, configuration: configuration)
if requiresDrawBackgroundFallback {
webView.setValue(false, forKey: "sward".reversed() + "background".capitalized) //drawsBackground KVC hack; works but private
}

customizing navbar with image as a title

I want to add a image in the navbar as title. I'm using the following code in AppDelegate.m file
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"akskeving_logo.png"]];
I'm gettin the following error: Property 'navigationItem'not found on object of type 'HsAppDelegate'
You are trying to access the navigationItem property of your app delegate, but it doesn’t have that property. navigationItem is a property of UIViewController. Something along these lines (details may be different for your app):
self.rootViewController.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"akskeving_logo.png"]];
Edit: actually, that is probably not exactly what you want to do. You should be accessing the navigationItem of the view controller that you are presenting in the navigation controller. So,
self.somePresentedViewController.navigationItem.titleView = …;

NSTextView displaying HTML via Cocoa Bindings

I've got a string with some simple HTML in it (mainly just and tags). I'm displaying them in an NSTextView using Cocoa Bindings. Unfortunately the html just shows up inline, it doesn't actually change the formatting. Is there a way to do get the html to render using bindings? If not, how would you do it?
Turns out it's fairly straightforward. The NSTextView bindings panel in Interface Builder has a "Value" section at the top, and the first choice is Attributed String. Just bind the Attributed String to an NSAttributedString property on your model object. You can create the attributed string from a normal string with html tags in it like so:
NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTML:data
baseURL:nil
documentAttributes:nil];
I don't know how much HTML you can cram in there (maybe javascript doesn't work) but basic stuff like stylesheets seems to work fine.
Swift 5:
let data = htmlString.data(using: .utf8)!
if let attributedString = NSAttributedString(html: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
{
textView.textStorage?.append(attributedString)
textView.textColor = .labelColor
textView.font = NSFont.systemFont(ofSize: 15)
}

Can a non-editable NSTextView highlight links using setAutomaticLinkDetectionEnabled?

I've been using a NSTextView to display some non-editable text and would like to highlight any links within it's string. I've seen some code that parses out the links and adds attributes. That would work fine, but I was wondering if I could somehow reuse the built-in link detection somehow.
I've tried setting:
[textView setEnabledTextCheckingTypes:NSTextCheckingTypeLink];
[textView setAutomaticLinkDetectionEnabled:YES];
and using:
[textView checkTextInDocument:nil];
after setting the string.
For the sake of completeness, here is how I've manually added links to a NSTextView:
- (void)highlightLinksInTextView:(NSTextView *)view {
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:view.string options:0 range:NSMakeRange(0, view.string.length)];
[view.textStorage beginEditing];
for (NSTextCheckingResult *match in matches) {
if (!match.URL) continue;
NSDictionary *linkAttributes = #{
NSLinkAttributeName: match.URL,
};
[view.textStorage addAttributes:linkAttributes range:match.range];
}
[view.textStorage endEditing];
}
Unfortunately you have to call this every time you set the NSTextView string.
I recently stumbled upon this and created an NSTextView subclass, LinkDetectingTextView.swift. Hope this helps someone in the future.

Fuzzy text with Core-Plot and NSViewController

I am using an NSViewController to load a nib with a view that renders a Core-Plot chart. I replace the "target view" using the following code:
NSViewController* aViewController = [[NSViewController alloc] initWithNibName:#"nib name" bundle:nil];
if (aViewController != nil)
{
myCurrentViewController = aViewController;
}
// embed the current view to our host view
[myTargetView addSubview: [myCurrentViewController view]];
[[myCurrentViewController view] setFrame: [myTargetView bounds]];
This results in basically everything in the chart looking slightly fuzzy. I commented out the setFrame and also tried integer values for the setFrame and it made no difference. The target view also does not have layering on.
If I get rid of the view controller and change myTargetView to the actual chart view class(PlotView) then it is no longer fuzzy. This is on 10.8. Any idea why using the NSViewController route is messing up the chart view?
Update #1: I am using from the Plot_Gallery_Mac sample project the PlotGalleryController, PlotView, PlotItem, and VerticalBarChart to generate the chart through an NSViewController. I am guessing the setup in the sample PlotItem class (particularly the renderInView method) is not compatible with using it with an NSViewController.

Resources