Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mapping for attributes of range #3

Open
gregpardo opened this issue Oct 7, 2015 · 7 comments
Open

Support mapping for attributes of range #3

gregpardo opened this issue Oct 7, 2015 · 7 comments

Comments

@gregpardo
Copy link

So I really like this project. I've been looking for something like it. I would like to suggest a feature. Sometimes you need attributes that are over the entire string...

let regAttributes = [NSFontAttributeName: UIFont.systemFontOfSize(12)]
let boldAttributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(12)]
let attrString = NSMutableAttributedString(string: "This is regular text.  ", attributes: regAttributes)
let boldString = NSMutableAttributedString(string: "This is bold text. ", attributes: boldAttributes)
let lastString = NSMutableAttributedString(string: "This is regular text again.", attributes: regAttributes)
attrString.appendAttributedString(boldString)
attrString.appendAttributedString(lastString)

What I'm proposing, and maybe I can help with, is an easy way to build strings like this in some sort of chainable way.

Perhaps a new extension can be created similar to 'make' or we can extend make to check for types and pass it an array of '(make: NSAttributedStringAttributeBuilder)' and at the concat all the strings together and return.

@SRandazzo
Copy link
Owner

@gregpardo Thanks for the kind words!

I like your proposed idea a lot, and can see why it would be really useful! Has me thinking we can achieve this with some functional composition. How about we brainstorm on an ideal syntax

let builder = NSAttributedStringAttributeBuilder()
builder.setAttribute(.Font(UIFont.systemFontOfSize(12)))

let multiString: NSAttributedString = 
"This is regular text"
>>> builder
>>> "this is bold text."
>>> builder.setAttribute(.Font(UIFont.boldSystemFontOfSize(12)))
>>> "this is regular text again"
>>> builder.setAttribute(.Font(UIFont.systemFontOfSize(12)))

@gregpardo
Copy link
Author

Perhaps sticking with the same style syntax is possible....

let attributedString = NSAttributedString.make( { (make: NSAttributedStringAttributeBuilder) -> Void in
    make.nextString("This is regular text")    
    make.setAttribute(.Font(UIFont.systemFontOfSize(12)))
    make.nextString("This is bold text")
    make.setAttribute(.Font(UIFont.boldSystemFontOfSize(12)))
    make.nextString("This is regular text again")
    make.setAttribute(.Font(UIFont.systemFontOfSize(12)))
})

Basically it could work like this

  1. Create new method that does not take string as first parameter
  2. Set the builder to multi mode
  3. At each occurrence of newString build the last string with attributes and push it onto an array (if its not the first)
  4. Use NSMutableAttributeString to concat all them

Some other ideas for methods.

make.setRetainAttributesOnNextString(enabled: Bool = false)

I could see situations where you would want to keep the last set of attributes and mutate them. By default it should probably clear every time a nextString occurs.

make.clearAttributes() 

Force a fresh set of attributes

make.addAttributes(attributes: NSAttributeDictionary)

Appends a group of attributes. Any existing attributes with same keys will be overwritten

make.removeAttribute(key: NSAttributedStringAttribute)

Remove an existing attribute

I like the functional approach but maybe that would be a good optional syntax. Closures seem to be a pretty standard swift idea. Let me know your thoughts and love/hate on any ideas here.

@SRandazzo
Copy link
Owner

Sorry for the delay getting back!

Read through your proposal, love it all! Seems well thought out and like it would be super useful!

I liked this idea a lot too:
make.setRetainAttributesOnNextString(enabled: Bool = false) as it keeps the API flexible

we could even pair the syntax closely to clearAttributes and do something like make.clearsAttributesOnNextString = true/false

For the actual storing of strings as we build them:

At each occurrence of newString build the last string with attributes and push it onto an array (if its not the first)

I am wondering if there is any merit in internally using multiple NSAttributedStringAttributeBuilders. ie. each nextString would internally create a new NSAttributedStringAttributeBuilder, and you would simply be putting those onto the stack.

Then you could just do a reduce on the array of builders to generate your final string. This would offer some API flexibility if you choose to not use the make closure. Then again, it's added complexity!

I say go for which ever approach! I'm excited to have this addition to the library, thanks for your effort!

@gregpardo
Copy link
Author

https://github.com/gregpardo/Verona/tree/develop

Let me know if you have suggestions. I haven't updated any tests or anything like that yet.

@SRandazzo
Copy link
Owner

Looking great so far! go on a head and pull request that back and i'll add a few comments 👍

awesome work!

On the note of testing, are you familiar with snapshot tests?

@gregpardo
Copy link
Author

I just got back into iOS and I don't think that project was around when I was working on it before. So not really but I did look into a little bit.

@SRandazzo
Copy link
Owner

Being addressed here: #6

Will close this issue after merged 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants