Numeric Types Don't Automatically Bridge to Nsnumber in Pure Swift on Ubuntu Linux

Numeric types don't automatically bridge to NSNumber in pure Swift on Ubuntu Linux?

There is no automatic bridging to NSNumber on Linux. Source:
NSNumber bridging and Numeric types:

Considerations for Linux platforms

We do not have bridging on Linux so the as? cast is less important; but if it were to have bridging this would be the desired functionality.

Is it possible to replicate Swifts automatic numeric value bridging to Foundation (NSNumber) for (U)Int8/16/32/64 types?

Yes (it's possible): by conformance to protocol _ObjectiveCBridgeable

(The following answer is based on using Swift 2.2 and XCode 7.3.)

Just as I was pondering over whether to post or simply skip this question, I stumbled over swift/stdlib/public/core/BridgeObjectiveC.swift in the Swift source code, specifically the protocol _ObjectiveCBridgeable. I've briefly noticed the protocol previously at Swiftdoc.org, but in its current (empty) blueprint form in the latter, I've never given much thought to it. Using the blueprints for _ObjectiveCBridgeable from the Swift source we can, however, swiftly let some native of custom type conform to it.

Before proceeding, note that _ObjectiveCBridgeable is an internal/hidden protocol (_UnderScorePreFixedProtocol), so solutions based on it might break without warning in upcoming Swift versions.


Enabling Int64 bridging to Foundation class NSNumber

As an example, extend Int64 to conform to _ObjectiveCBridgeable, and subsequently test if this quite simple fix is sufficient for the implicit type conversion (bridging) from Int64 to Foundation class NSNumber holds.

import Foundation

extension Int64: _ObjectiveCBridgeable {

public typealias _ObjectiveCType = NSNumber

public static func _isBridgedToObjectiveC() -> Bool {
return true
}

public static func _getObjectiveCType() -> Any.Type {
return _ObjectiveCType.self
}

public func _bridgeToObjectiveC() -> _ObjectiveCType {
return NSNumber(longLong: self)
}

public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) {
result = source.longLongValue
}

public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) -> Bool {
self._forceBridgeFromObjectiveC(source, result: &result)
return true
}
}

Test:

/* Test case: scalar */
let fooInt: Int = 42
let fooInt64: Int64 = 42
var fooAnyObj : AnyObject

fooAnyObj = fooInt // OK, natively
fooAnyObj = fooInt64 // OK! _ObjectiveCBridgeable conformance successful

/* Test case: array */
let fooIntArr: [Int] = [42, 23]
let fooInt64Arr: [Int64] = [42, 23]
var fooAnyObjArr : [AnyObject]

fooAnyObjArr = fooIntArr // OK, natively
fooAnyObjArr = fooInt64Arr // OK! _ObjectiveCBridgeable conformance successful

Hence, conformance to _ObjectiveCBridgeable is indeed sufficient to enable automatic by-assignment bridging to the corresponding Foundation class; in this case, NSNumber (in Swift, __NSCFNumber).


Enabling Int8, UInt8, Int16, UInt16, Int32, UInt32, (Int64), and UInt64 bridging to NSNumber

The above conformance of Int64 to _ObjectiveCBridgeable can easily be modified to cover any of the Swift-native integer types, using the NSNumber conversion table below.

/* NSNumber initializer:               NSNumber native Swift type property
-------------------------------- -----------------------------------
init(char: <Int8>) .charValue
init(unsignedChar: <UInt8>) .unsignedCharValue
init(short: <Int16>) .shortValue
init(unsignedShort: <UInt16>) .unsignedShortValue
init(int: <Int32>) .intValue
init(unsignedInt: <UInt32>) .unsignedIntValue
init(longLong: <Int64>) .longLongValue
init(unsignedLongLong: <UInt64>) .unsignedLongLongValue */

Swift on Ubuntu: use of undeclared type 'NSFileHandle'

From SE-0086 Drop NS Prefix in Swift Foundation:

As part of Swift 3 API Naming and the introduction of Swift Core Libraries, we are dropping the NS prefix from key Foundation types in Swift.

NSFileHandle is in that list and is called FileHandle in Swift 3:

import Foundation
let file = FileHandle(forReadingAtPath: "data.txt")

This applies to the Apple platforms and to Linux.
The Linux implementation can be seen here:
NSFileHandle.swift.

There is a discussion [swift-evolution] Pitch: Replacement for FileHandle
about undoing the renaming and implementing FileHandle in a more
Swift-like manner (such as throwing Swift errors instead of
NSExceptions).

How to convert Int to int in swift?

You just do value = number

As you can see in the documentation:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html

the native swift number types generally bridge directly to NSNumber.

Numbers

Swift automatically bridges certain native number types, such as Int and Float, to NSNumber. This bridging lets you create an NSNumber from one of these types:

SWIFT

let n = 42
let m: NSNumber = n
It also allows you to pass a value of type Int, for example, to an argument expecting an NSNumber. Note that because NSNumber can contain a variety of different types, you cannot pass it to something expecting an Int value.

All of the following types are automatically bridged to NSNumber:

Int
UInt
Float
Double
Bool

Swift 3 update

In Swift 3, this bridging conversion is no longer automatic and you have to cast it explicitly like this:

let n = 42
let m: NSNumber = n as NSNumber

Objective-C for Windows

Expanding on the two previous answers, if you just want Objective-C but not any of the Cocoa frameworks, then gcc will work on any platform. You can use it through Cygwin or get MinGW. However, if you want the Cocoa frameworks, or at least a reasonable subset of them, then GNUStep and Cocotron are your best bets.

Cocotron implements a lot of stuff that GNUStep does not, such as CoreGraphics and CoreData, though I can't vouch for how complete their implementation is on a specific framework. Their aim is to keep Cocotron up to date with the latest version of OS X so that any viable OS X program can run on Windows. Because GNUStep typically uses the latest version of gcc, they also add in support for Objective-C++ and a lot of the Objective-C 2.0 features.

I haven't tested those features with GNUStep, but if you use a sufficiently new version of gcc, you might be able to use them. I was not able to use Objective-C++ with GNUStep a few years ago. However, GNUStep does compile from just about any platform. Cocotron is a very mac-centric project. Although it is probably possible to compile it on other platforms, it comes XCode project files, not makefiles, so you can only compile its frameworks out of the box on OS X. It also comes with instructions on compiling Windows apps on XCode, but not any other platform. Basically, it's probably possible to set up a Windows development environment for Cocotron, but it's not as easy as setting one up for GNUStep, and you'll be on your own, so GNUStep is definitely the way to go if you're developing on Windows as opposed to just for Windows.

For what it's worth, Cocotron is licensed under the MIT license, and GNUStep is licensed under the LGPL.



Related Topics



Leave a reply



Submit