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 throw
ing Swift errors instead of NSException
s).
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
How to Make Function That Some Parameters Not Required in When Call It in iOS Swift 3
Insert a Comment Using the Youtube API and Alamofire
Swift Cannot Infer Type from Context
Swiftui: How to Switch to a New Navigation Stack with Navigationviews
Array Extension Called from Other Module
Set Custom Uiview Frame in Uiviewrepresentable Swiftui
Swift Use Unicode Character in Localization.Strings
Generic Method Override Not Working in Swift
Send Mail with File Attachment
How to Sort Dates in a Dictionary
Textfield in Swiftui Loses Focus When I Enter a Character
How to Use Nsvisualeffectview to Blend Window with Background
How to Customize the Title/Subtitle Font in Callout from Mkannotationview or Just Hide Them
Swift Struct with Lazy, Private Property Conforming to Protocol
Swiftui Share Sheet Crashes iPad
Swiftui - Unwrap Optional Image Data to Create Image Based on Uiimage(Data)