0

Okay I'm having an issue with NSAttributeString. I'm getting different html/css strings that occupy "busDescriptio" depending on what business you choose from a website database. I'm able to customize the string as I see fit as NSAttributeString but unfortunately on some cases the string already has css scripting in it which overrides my style that I insert into the string. Is it possible to override the scripting that is within my string? If so, how would I be able to do this? ***If I cant override the script can I just extract a certain tag from my string or replace it? Oh here is what my string looks like. As you see their is a style that is being poppulated within the string aka(busDescriptio). I'm not able to change that with regular scripting using NSAttributeString.

 /* This is a random description my busDescriptio pulls in which changes everytime someone selects a different business*/<p><span style="color:rgb(0, 0, 0); font-family:verdana,arial,tahoma; font-size:12px">Baxter Eye Care has been serving The Woodlands with quality eye care and personal friendly service since 1981. &nbsp;Dr. Baxter, Dr. Daniels and Dr. Shosa are dedicated to your eye health and vision needs.</span></p>

This is the code I'm using to do this

extension String {
    var html2String:String {
        return NSAttributedString(data: dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil, error: nil)!.string
    }
    var html2NSAttributedString:NSAttributedString {
        return NSAttributedString(data: dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil, error: nil)!
    }
}
extension NSData{
    var htmlString:String {
        return  NSAttributedString(data: self, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil, error: nil)!.string
    }
}
let result = html2String("\(busDescriptio)") // Business Description HTML

            let yourAttributedText = "<style type=\"text/css\">#busDescriptio{color:white;align-content:left;}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"busDescriptio\" >\(result),</span><span id=\"green\" > Green </span><span id=\"blue\">and Blue</span>".html2NSAttributedString

            // Create UITextView
            var textView = UITextView(frame: CGRectMake(0, 95.0, screenWidth-10, 300.0))
            textView.attributedText = yourAttributedText
            textView.backgroundColor = UIColor.clearColor()
            textView.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)

            border.addSubview(textView)
func html2String(html:String) -> String {
        return NSAttributedString(data: html.dataUsingEncoding(NSUTF8StringEncoding)!, options:[NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil, error: nil)!.string
    }
Thomas Martinez
  • 1,631
  • 3
  • 16
  • 21
  • You can extract the regular string from your html code and add your attributes to the extracted string – Leo Dabus Mar 05 '15 at 22:05
  • 1
    http://stackoverflow.com/questions/27661722/removing-everything-between-a-certain-set-of-characters-with-swift/27662573#27662573 – Leo Dabus Mar 05 '15 at 22:06
  • hey! saving my life again I see haha. I was going to ask you this on the previous question but it was off topic! Thanks for the help again. I'm looking into it right now – Thomas Martinez Mar 05 '15 at 22:08
  • You are welcome. Just up vote it if it solves your problem. – Leo Dabus Mar 05 '15 at 22:09
  • Yea I'm looking into how you did this. Pretty impressive! I will as soon as I can put it together! – Thomas Martinez Mar 05 '15 at 22:10
  • https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/index.html – Leo Dabus Mar 05 '15 at 22:30
  • Okay so this is similar to my last question I was able to extract just the string but this takes away all my tags which includes images and links. How can I pinpoint how to get rid of a certain tag such as tags – Thomas Martinez Mar 05 '15 at 23:52
  • http://stackoverflow.com/a/25882504/2303865 – Leo Dabus Mar 05 '15 at 23:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/72441/discussion-between-tom-and-leonardo-savio-dabus). – Thomas Martinez Mar 06 '15 at 22:50
  • I realized that by removing this tag everything between it becomes part of my text which I dont want. I'm not sure how to do this..blahh this sux. All I want to do is tell all my NSAttributedString to behave the way I want it to even overriding scripting that is within the string. I tried UIWebview it doesnt work and NSAttributeString does the samething. Its like those styles are invincible to coding above it – Thomas Martinez Mar 06 '15 at 23:23

2 Answers2

3

I think you're stuck thinking about HTML. Once you have created an NSAttributedString or, more accurately, an NSMutableAttributedString from the HTML, you can just apply your own attributes. At that point, the HTML is no longer relevant. You certainly shouldn't try to achieve formatting by manipulating the HTML before converting it into an attributed string.

You don't say what "style" or attributes you want to change, so it's hard to give you an example, but just set or remove whatever attributes you want. You have the power to completely override whatever styling was introduced by the CSS in the HTML.

For example, do [someMutableAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0, someMutableAttributedString.length)] to change the color to blue.


Here's some Objective-C code which works for me on OS X:

NSString* html = @"<style type=\"text/css\">#busDescriptio{color:white;align-content:left;}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"busDescriptio\" ><p><span style=\"color:rgb(0, 0, 0); font-family:verdana,arial,tahoma; font-size:12px\">Baxter Eye Care has been serving The Woodlands with quality eye care and personal friendly service since 1981. &nbsp;Dr. Baxter, Dr. Daniels and Dr. Shosa are dedicated to your eye health and vision needs.</span></p>,</span><span id=\"green\" > Green </span><span id=\"blue\">and Blue</span>";
NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding];

NSMutableAttributedString* str = [[NSMutableAttributedString alloc] initWithData:data
                                                                         options:@{ NSCharacterEncodingDocumentOption: @(NSUTF8StringEncoding),
                                                                                    NSDocumentTypeDocumentOption: NSHTMLTextDocumentType }
                                                              documentAttributes:NULL
                                                                           error:NULL];
[str addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(0, str.length)];
self.label.attributedStringValue = str;

I don't work in Swift, but here's a pass at a simple translation:

let html = "<style type=\"text/css\">#busDescriptio{color:white;align-content:left;}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"busDescriptio\" ><p><span style=\"color:rgb(0, 0, 0); font-family:verdana,arial,tahoma; font-size:12px\">Baxter Eye Care has been serving The Woodlands with quality eye care and personal friendly service since 1981. &nbsp;Dr. Baxter, Dr. Daniels and Dr. Shosa are dedicated to your eye health and vision needs.</span></p>,</span><span id=\"green\" > Green </span><span id=\"blue\">and Blue</span>"
let data = html.dataUsingEncoding(NSUTF8StringEncoding)!

var str = NSMutableAttributedString(data:data,
                                    options:[ NSCharacterEncodingDocumentOption: NSUTF8StringEncoding,
                                              NSDocumentTypeDocumentOption: NSHTMLTextDocumentType ],
                                    documentAttributes:nil,
                                    error:nil)
str.addAttribute(NSForegroundColorAttributeName, value:NSColor.redColor(), range:NSMakeRange(0, str.length))
self.label.attributedStringValue = str;

So, the code starts with HTML code in a string. It creates an NSMutableAttributedString from that. Then it changes the foreground color, effectively replacing the color resulting from the HTML. Finally, it sets the attributed string as the content of an NSTextField label. For iOS, you could use a UILabel or UITextView or whatever.

In the code you put in your question, there are some things that are troublesome. It's not clear what busDescription is. Is it a string containing HTML code?

Is there a reason that you're interpolating it into a string to pass it to html2String()? That is, why this:

let result = html2String("\(busDescriptio)")

and not this:

let result = html2String(busDescriptio)

?

It seems that html2String() interprets HTML into an attributed string and then just extracts the plain text from that. Why are you doing that?

You are then interpolating that plain text into another block of HTML code. Again, why are you doing that? If you want to apply colors, fonts, etc. to the plain text string, just build an attributed string directly from that plain text string — no HTML involved — and apply the desired attributes.

Or, start from the original busDescriptio, make a mutable attributed string from that HTML code, and apply whatever attributes you like to that.

For example, here's another example:

NSString* busDescriptio = @"<p><span style=\"color:rgb(0, 0, 0); font-family:verdana,arial,tahoma; font-size:12px\">Baxter Eye Care has been serving The Woodlands with quality eye care and personal friendly service since 1981. &nbsp;Dr. Baxter, Dr. Daniels and Dr. Shosa are dedicated to your eye health and vision needs.</span></p>";
NSData* data = [busDescriptio dataUsingEncoding:NSUTF8StringEncoding];
NSMutableAttributedString* foo = [[NSMutableAttributedString alloc] initWithData:data
                                                                         options:@{ NSCharacterEncodingDocumentOption: @(NSUTF8StringEncoding),
                                                                                    NSDocumentTypeDocumentOption: NSHTMLTextDocumentType }
                                                              documentAttributes:NULL
                                                                           error:NULL];
[str addAttribute:NSFontAttributeName value:[NSFont fontWithName:@"Verdana" size:12] range:NSMakeRange(0, str.length)];

Basically, although your initial input is HTML code, you build a mutable attributed string from that and then don't work in HTML from that point on. Just apply and/or remove attributes from the attributed string, as desired. You can also build separate attributed strings, like your green or blue text in your example, and append those to the mutable one.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • I gave you some of my code to to show you what I'm doing. Is there a way you can use this to show me? If not its cool! Thanks! – Thomas Martinez Mar 06 '15 at 19:59
  • Okay I tried your code although it does change the color I'm still having all the tags show up with no images or links so it became blue but text are saying

    Fresh Seafood and USDA Prime Steak Directory from OUR OWN MARKET!

    – Thomas Martinez Mar 06 '15 at 22:35
  • I've edited my answer with more sample code and explanation. I'm not sure what to make of the code you posted. Also not sure why you are ending up with HTML code in your result. I assume you're not doing what I've recommended. – Ken Thomases Mar 07 '15 at 03:18
  • Wow THANK YOU for this amazing response! I will decipher your code and see how to do that. Oh and to respond to your questions, I have no clue what I'm exactly doing. I tried all kinds of ways and either it takes all my tags away or doesnt work for all of my description when I change font colors and ext. Okay busDescriptio is a string that I inherit from a database that I'm parsing from that contains descriptions of businesses in html and sometimes css. scripting Now these businesses description will change along with html and inserted css scripting when user picks a different business – Thomas Martinez Mar 07 '15 at 04:34
  • This def works! I had to make a few changes but it does what I want. Now I only have one more question! Its related because even though I'm using this code certain images arent coming through it looks like but nothing shows for this in the textview. It may be because its an internal link? if so what do you do for this? – Thomas Martinez Mar 09 '15 at 17:41
  • 1
    The URL for the image is presumably relative to the URL of the page the HTML is considered to come from. By the time you're creating the attributed string from the HTML, it's no longer associated with a URL, so the system can't construct an absolute URL for the image and can't find it. You can specify the base URL in the options passed to `-initWithData:options:documentAttributes:error:` with the key `NSBaseURLDocumentOption`. – Ken Thomases Mar 09 '15 at 18:26
  • would that be in the mixture of options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding] or like at the end where like documentAttributes:nil, error:nil, baseUrl:mybaseUrl)! – Thomas Martinez Mar 09 '15 at 18:43
  • It would be in the options dictionary along with `NSDocumentTypeDocumentAttribute`, etc. You could also switch from using `-initWithData:options:documentAttributes:error:` to using one of the `-initWithHTML:...` methods. If you pick the right one, all of the options are implied by which method you selected and the arguments you supply. – Ken Thomases Mar 09 '15 at 18:57
  • Oh okay so when I put it into my options dictionary its giving me an error saying use of unresolved identifier 'NSBaseURLDocumentOption' – Thomas Martinez Mar 09 '15 at 19:13
  • Oh, crud. Sorry. That's only available on OS X, not iOS. I'm not seeing a solution that's available on iOS. (Also, ignore what I said about the `-initWithHTML:...` methods, as those are not available on iOS, either.) – Ken Thomases Mar 09 '15 at 19:18
  • Okay I looked at my mac and it says its an OS X. Are you referring to a different plateform for making an apple app? – Thomas Martinez Mar 09 '15 at 19:34
  • You're developing an app **for** iOS. You can only use features provided by that OS. It doesn't matter that you're building the app on OS X. – Ken Thomases Mar 09 '15 at 19:36
  • Yea I just checked it out! Well thanks for all the help. I hope there is something out there that I can give a base url in soon! – Thomas Martinez Mar 09 '15 at 19:40
  • Quick question! Should I use something like this for swift? Will this work? http://www.raywenderlich.com/4147/core-text-tutorial-for-ios-making-a-magazine-app – Thomas Martinez Mar 10 '15 at 04:26
  • Huh? The language you program in shouldn't affect what works or not. Of course, you would have to translate the code from Objective-C to Swift if you want to code it in Swift. In any case, what part of that were you looking to use? How would you expect it to help with the issue in this question? (Or was this not about this question?) – Ken Thomases Mar 10 '15 at 04:57
0

Okay so using what Ken Thomases wrote I was able to make it work! After looking at his code and seeing what I did wrong I was able to make it work. Here it is in Swift code just in case anyone has the same problem I had. I'm still having trouble with some images but ideally everything from font color, size, height, alignments and background work! Thanks

// busDescriptio is being occupied by a string with html and css scripting
var data: NSData = busDescriptio.dataUsingEncoding(NSUTF8StringEncoding)!
            var foo: NSMutableAttributedString = NSMutableAttributedString(data: data,
                options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding],
            documentAttributes:nil,
            error:nil)!
            var paragraph = NSMutableParagraphStyle()
            paragraph.alignment = NSTextAlignment.Left
            foo.addAttribute(NSFontAttributeName, value: UIFont(name: "Arial", size:12)!, range:NSMakeRange(0, foo.length))
            foo.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSRange(location:0,length: foo.length))
            foo.addAttribute(NSBackgroundColorAttributeName, value: UIColor.clearColor(), range: NSRange(location: 0, length: foo.length))
            foo.addAttribute(NSParagraphStyleAttributeName, value:paragraph, range:NSMakeRange(0, foo.length))
Thomas Martinez
  • 1,631
  • 3
  • 16
  • 21