[swift-users] Importing NSUInteger in my own Objective-C Code as Int

Jordan Rose jordan_rose at apple.com
Tue Jan 19 13:43:08 CST 2016

> On Jan 17, 2016, at 13:01, Chris Lattner via swift-users <swift-users at swift.org> wrote:
>> On Jan 15, 2016, at 10:19 AM, Jens Alfke via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>> On Jan 15, 2016, at 5:19 AM, Marco Masser via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>> Swift imports NSUInteger in Objective-C APIs as Int, but only for Frameworks like Foundation and AppKit. For other code, NSUInteger is imported simply as UInt.
>> Really? I’d never noticed that. It seems wrong to me, since NSUInteger is clearly an unsigned type, so it should map to Uint.
> Yes, it is intentional, we do the same for size_t.
> As far as I know, there is no way to get the same behavior for your own code.  It would be reasonable to introduce a clang attribute for that though.

I've been meaning to do an investigation to see about just doing this automatically for user code—i.e. how many of the top frameworks in CocoaPods are using NSUInteger to really mean "word-sized unsigned integer", as opposed to "the Apple framework uses NSUInteger here so I will too".

By the way, the original rational for the NSUInteger -> Int mapping is mostly that our frameworks weren't consistent about the use of NSInteger/CFIndex vs. NSUInteger. Since Swift makes signedness conversions explicit, this would become an unnecessary burden. (For example, -[UITableViewDataSource numberOfSectionsInTableView:] <https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/index.html#//apple_ref/occ/intfm/UITableViewDataSource/numberOfSectionsInTableView:>  uses NSInteger, but NSArray.count <https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/index.html#//apple_ref/occ/instp/NSArray/count> uses NSUInteger.) We found that there would almost never be an NSUInteger value that actually went beyond NSIntegerMax, at least partly because this is the representation of NSNotFound <https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/#//apple_ref/doc/constant_group/NSNotFound>. In cases where there was a value that went past NSIntegerMax, it was usually a unique identifier or a bitfield, i.e. not something that needed arithmetic operations. Since Swift doesn't have strange undefined behavior around its bitwise operations for signed types, there's no problem bringing these sorts of values in as Int as well. Similar arguments apply to size_t and rsize_t, which never actually have to represent an integer spanning half of the address space. (If you actually need such a thing for non-size-related reasons, the right type would be uintptr_t, which is imported as UInt.)

One exception is that we do keep the base of NS_OPTIONS enums as NSUInteger if so specified. In that case, we want to keep the integer constant valid as is and not force a spurious minus sign on the 32nd option.

The main loss here is that NSUInteger always carries the precondition of the value being non-negative, but again, existing frameworks already weren't consistent about that, so we considered it an acceptable trade-off.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160119/e6402267/attachment.html>

More information about the swift-users mailing list