So my Character.isMemberOfSet() is a poor general-purpose method, and I need to
ditch it.
I like your code. I had to modify it a bit so it wouldn’t fall on strings
composed entirely of whitespace:
let testString = " \n\n \t\t"
let attrStr = NSAttributedString( string:testString )
let str = attrStr.string as NSString
let notWhitespace =
NSCharacterSet.whitespaceAndNewlineCharacterSet().invertedSet
var resultRange:NSRange
let startRange = str.rangeOfCharacterFromSet( notWhitespace,
options:NSStringCompareOptions.allZeros )
if startRange.length > 0 {
let endRange = str.rangeOfCharacterFromSet( notWhitespace,
options:NSStringCompareOptions.BackwardsSearch )
let startIndex = startRange.location
let endIndex = endRange.location + endRange.length
resultRange = NSRange( location:startIndex, length:endIndex - startIndex )
} else {
// String is empty or all whitespace
resultRange = NSRange( location:0, length:0 )
}
let resultStr = attrStr.attributedSubstringFromRange( resultRange )
So, even though attrStr.string returns an NSString, you have use the “as” to
explicitly keep the type and be able to do math on range indexes. Lacking that
cast is what made rangeOfCharacterFromSet() useless to me yesterday.
Your code seems way better. but is there a way in the playground for use to
test addresses to make sure attrStr.string as NSString doesn’t perform a copy?
—
Charles
On April 3, 2015 at 2:04:01 PM, Quincey Morris
([email protected]) wrote:
On Apr 3, 2015, at 04:00 , Charles Jenkins <[email protected]> wrote:
for char in String( self ).utf16 {
if set.characterIsMember( char ) {
return true
}
Now we’re back to the place we started. This code is wrong. It fails for any
code point that isn’t representable a single UTF-16 code value, and it fails
for any grapheme that isn’t representable as a single code point.
This is what I would do (playground version):
import Cocoa
let notWhitespace =
NSCharacterSet.whitespaceAndNewlineCharacterSet().invertedSet
let attrStr = NSAttributedString( string:" Fourscore and seven years ago...
\n\n \t\t" )
let str = attrStr.string as NSString
let startRange = str.rangeOfCharacterFromSet(notWhitespace, options:
NSStringCompareOptions.allZeros)
let endRange = str.rangeOfCharacterFromSet(notWhitespace, options:
NSStringCompareOptions.BackwardsSearch)
let startIndex = startRange.length != 0 ? startRange.location : 0
let endIndex = endRange.length != 0 ? endRange.location + 1 : str.length
let resultRange = NSRange (location: startIndex, length: endIndex - startIndex)
let resultStr = attrStr.attributedSubstringFromRange (resultRange)
It’s the Obj-C code, just written in Swift. The ‘as NSString’ in the 3rd line
makes it work.
The practical difficulty in your original approach is that (e.g.)
String.rangeOfCharacterFromSet returns a Range<String.Index>, but AFAICT that
isn’t convertible back to a NSRange, or even just integer indexes. At the same
time, AFAICT it isn’t useful with a String because it doesn’t contain Character
indexes, just unichar indexes, which have no meaning for a String in general.
Actually, my testing is with Swift 1.1, since I’m not in a position to move to
Xcode 6.3 yet. It’s possible that the results are different in Swift 1.2.
However, in the section of the release notes that talks about bridging between
String and NSString, it says:
Note that these Cocoa types in Objective-C headers are still automatically
bridged to their corresponding Swift type
so I suspect the results would be the same in 1.2. It seems to me there is an
actual bug here:
“String methods corresponding to NSString methods that return NSRange values
actually return Range<String.Index> values, but these are not valid ranges,
either for String objects (they represent UTF-16 code value positions, not
Character positions) or for NSString objects (they’re not convertible back to
NSRange). The String methods ought to return NSRange values just like their
NSString counterparts.”
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]