2

I've seen a few options on here using just Objective-C, but I'm having trouble doing this with Swift iOS8 in XCode 6. I'm using the uiwebview to load a website. For sake of example, let's say its google.com.

@IBOutlet var website: UIWebView!

var url = "http://www.google.com"

func loadUrl() {
    let requestURL = NSURL(string: url)
    let request = NSURLRequest(URL: requestURL!)
    website.loadRequest(request)
}

override func viewDidLoad() {
    super.viewDidLoad()
    website.delegate = self
    loadUrl()
}

func webViewDidFinishLoad(website: UIWebView) {
    var jsscript = "some script here"
    website.stringByEvaluatingJavaScriptFromString(jsscript)
}

Using Swift, how would I inject a whole new stylesheet into the website so I can overwrite many of the styles?

Also, I'd like the new stylesheet to exist in one of my app's directories. Where is the best directory for that to be? Under "Supporting files?" And, how would I call that path in my code?

It would also be nice if the website wouldn't load until the styles had been applied.

Michael Sebastian
  • 785
  • 3
  • 15
  • 33

2 Answers2

4

So, I think I found at least one way to accomplish appending styles to the webpage being loaded using Swift:

  var loadStyles = "var script = 
  document.createElement('link');
  script.type = 'text/css';
  script.rel = 'stylesheet';
  script.href = 'http://fake-url/styles.css';
  document.getElementsByTagName('body')[0].appendChild(script);"

  website.stringByEvaluatingJavaScriptFromString(loadStyles)
Michael Sebastian
  • 785
  • 3
  • 15
  • 33
  • Hey thanks man! I have the same idea. Does anything needed to be added to the second CSS script to overwrite the other one? Like putting !important after every overwritten command? Thanks again! – Kragalon Apr 04 '15 at 04:17
  • Also, this doesn't seem to work for me. I wasn't able to get the `website.delegate = self` line to work, but does that part matter? – Kragalon Apr 04 '15 at 06:03
  • 1
    @kragalon in terms of css overwriting: Since CSS is hierarchical, just having your new styles load below the website's styles should overwrite the site's styles. By below I mean it is called last after the other css styles are called. However, if the site's styles use the !important script for any of its elements, you too will need to add the !important script to overwrite that element. – Michael Sebastian Apr 06 '15 at 14:10
  • @Kragalon could you give more detail in terms of your other problem involving the website delegate? Where in the code are you setting it? – Michael Sebastian Apr 06 '15 at 14:11
  • 1
    I know this was asked a while ago but to set website.delegate = self, you need to pass UIWebViewDelegate in your main class. – SMULLER May 27 '15 at 17:28
1

Using the now preferred WKWebView you can put the external css file, say tweaks.css in the root of your project or in a sub-folder, then you can inject it into your page like this:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    guard let path = Bundle.main.path(forResource: "tweaks", ofType: "css") else { return }
    let css = try! String(contentsOfFile: path).replacingOccurrences(of: "\\n", with: "", options: .regularExpression)
    let js = "var style = document.createElement('style'); style.innerHTML = '\(css)'; document.head.appendChild(style);"
    webView.evaluateJavaScript(js)
}

To make the file available:

  1. Click your project
  2. Click your target
  3. Select Build Phases
  4. Expand Copy Bundle Resources
  5. Click '+' and select your file.

Also make sure that your controller implements WKNavigationDelegate:

class ViewController: UIViewController, WKNavigationDelegate 
Jannie Theunissen
  • 28,256
  • 21
  • 100
  • 127