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 
(quinceymor...@rivergatesoftware.com) wrote:

On Apr 3, 2015, at 04:00 , Charles Jenkins <cejw...@gmail.com> 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 (Cocoa-dev@lists.apple.com)

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 arch...@mail-archive.com

Reply via email to