withUnsafeBytes with Swift 3.1 and iOS 9.3 - swift

I use a method within my code to convert raw bytes to Ints.
The code I used previously was:
func convert(from data: Data) -> Int? {
return data.withUnsafeBytes { $0.pointee }
}
This used to work correctly, until XCode 8.3 with Swift 3.1 support came along. Now the same method works correctly on iOS 10 devices, but fails (returns absurdly large numbers) on devices (and simulators) running iOS 9.3.
Example code: Data(bytes: [0]).withUnsafeBytes { $0.pointee } as Int returns -4611686018427387903
Anyone experiencing the same issue?

Related

Using previewCGImageRepresentation in both Xcode 13 and Xcode 12?

I’ve run into an issue where Xcode 13b2 (iOS 15 SDK) changed the Swift return type of AVCapturePhoto.previewCGImageRepresentation(). In Xcode 12.5.1 (iOS 14 SDK), this method returns Unmanged<CGImage>. In 13b2 - 13b4, it returns CGImage?.
I need my code to compile under both Xcode versions, since Xcode 13 has other issues, and can’t be used to submit builds to the App Store. I thought I was clever writing this, but it won’t compile, because it’s not conditional code compilation check but rather a runtime check:
extension AVCapturePhoto {
func stupidOSChangePreviewCGImageRepresentation() -> CGImage? {
if #available(iOS 15, *) {
return self.previewCGImageRepresentation()
} else {
return self.previewCGImageRepresentation()?.takeUnretainedValue()
}
}
}
Another possibility might be to create a user-defined Xcode setting, but I don’t think that can be done conditionally based on Xcode or SDK version.
There might be some unsafe pointer histrionics one can do…
Any other ideas?
You can make a check on the swift compiler version. An exhaustive list is available on wikipedia at the time of writing.
https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
extension AVCapturePhoto {
func stupidOSChangePreviewCGImageRepresentation() -> CGImage? {
#if compiler(>=5.5)
return self.previewCGImageRepresentation()
#else
return self.previewCGImageRepresentation()?.takeUnretainedValue()
#endif
}
}

Conditional Conformance to Hashable

With Xcode 10, and Swift 4.2 there are additional types that conform to Hashable as long as their elements also conform to Hashable (Array, Dictionary, etc).
I currently have some code in my project to add Hashable conformance for Swift 4.1 and below like this:
extension Array: Hashable where Element: Hashable {
public var hashValue: Int {
let prime = 31
var result = 1
for element in self {
result = prime * result + element.hashValue
}
return result
}
}
However, even if I add #if !swift(>=4.2) around the code I still see the same warning in Xcode.
My question is, how can I keep the conditional conformance to Hashable for Swift 4.1 and below, but silence the warning for Swift 4.2?
The conditional compilation statement #if swift(...) checks against the language version you're running with – which can differ from the compiler (and therefore standard library) version.
In your case, it sounds like you're using a Swift 4.2 compiler in Swift 4 compatibility mode, which gives you a language version of 4.1.50. This therefore passes the conditional compilation statement and your extension is compiled, giving you a duplicate conformance.
In order to check for a compiler version less than 4.2, you want the following:
// less than 4.2 in Swift 4 compat mode and (less than 4.2 in 3 compat mode or
// greater than 4).
#if !swift(>=4.1.50) && (!swift(>=3.4) || swift(>=4.0))
extension Array : Hashable where Element : Hashable {
public var hashValue: Int {
let prime = 31
var result = 1
for element in self {
result = prime * result + element.hashValue
}
return result
}
}
#endif
Things will be much better with the new #if compiler directive, which is available in Swift 4.2 from Xcode 10 beta 4 onwards (confirmed by #MartinR). With that, you can directly test for the compiler version, ignoring any compatibility modes it might be running in.
This doesn't help your specific case as you need the code to be understood by both Swift 4.2 and 4.1 compilers (as also pointed out by Martin), but for future compatibility problems, you could for example use #if !compiler(>=5) in order to only compile a block of code if using a 4.2 compiler.

Does _ArrayType or _ArrayProtocol not available in Swift 3.1?

I was using _ArrayType in my project when I was running on swift 2.1. I upgraded to swift 3.0.2 (Xcode 8.2.1) last week and I found here that _ArrayType is changed to _ArrayProtocol and it was working well.
Today I upgraded my Xcode to 8.3.1, and it gives me error:
Use of undeclared type '_ArrayProtocol'. Here is my code:
extension _ArrayProtocol where Iterator.Element == UInt8 {
static func stringValue(_ array: [UInt8]) -> String {
return String(cString: array)
}
}
What's wrong now? Why _ArrayProtocol is undeclared in swift 3.1 while it was working in swift 3.0.2.
Also when I look here in git I see _ArrayProtocol available.
Than I looked into Swift 2.1 docs I am able to see '_ArrayType' in protocol listing but in Swift 3.0/3.1 docs I am not able to see _ArrayProtocol.
Type names starting with an underscore should always treated as internal.
In Swift 3.1, it is marked as internal in the source code and therefore
not publicly visible.
Using _ArrayProtocol was a workaround in earlier Swift versions where
you could not define an Array extension with a "same type" requirement.
This is now possible as of Swift 3.1, as described in the
Xcode 8.3 release notes:
Constrained extensions allow same-type constraints between generic parameters and concrete types. (SR-1009)
Using the internal protocol is therefore not necessary anymore,
and you can simply define
extension Array where Element == UInt8 {
}
But note that your static func stringValue() does not need any
restriction of the element type. What you perhaps intended is to
define an instance method like this:
extension Array where Element == UInt8 {
func stringValue() -> String {
return String(cString: self)
}
}
print([65, 66, 67, 0].stringValue()) // ABC
Also note that String(cString:) expects a null-terminated sequence
of UTF-8 bytes.

Xcode 8.0 conversion issue

AS I have updated the XCode to 8, new version, the following code
func center(_ usePresentationLayer: Bool) -> CGPoint
{
if usePresentationLayer, let presentationLayer = layer.presentation() as! CALayer
{
return presentationLayer.position
}
return center
}
result in
Error - Value of type 'CALayer' has no member 'presentation'
How can I fix this issue in XCode using swift 3.0?
Edit: the question changed
Make sure request is of type URLRequest.
Don't upload screenshots of code - please edit your post so it contains code that's searchable.

Use NSRunningApplications? [duplicate]

This question already has answers here:
Filtering user-launched applications (Mac OS X)
(2 answers)
Closed last month.
I am trying to have my OS X Application detect if a certain program is running but NSRunningApplications isn't working for me. This is my code:
import AppKit
class func sharedWorkspace() -> NSWorkspace
{
var runningApplications: [NSRunningApplications] {get}
}
The error I'm getting is
Expected '{' to start getter definition.
as well as
Missing return in a function expected to return 'NSWorkspace.
Any ideas?
You've got to use NSWorkspace.sharedWorkspace().runningApplications itself:
for app in NSWorkspace.sharedWorkspace().runningApplications {
if let name = app.localizedName {
print(name)
}
}
You can get the running applications names in an array with a simple map (or flatMap here to manage Optionals):
let names = NSWorkspace.sharedWorkspace().runningApplications.flatMap { $0.localizedName }
print(names)
In Swift 5+ the syntax changed to:
NSWorkspace.shared.runningApplications