I have the following class:
class RawDataArray {
var data: NSData!
init(filePath: String) {
data = NSData(contentsOfFile: filePath)
}
func read<T>(offset: Int) -> T {
return UnsafePointer<T>(data.bytes + offset).memory
}
}
which I use in my iOS app to read from a binary file with a custom format. For example, to read an Int at offset 5, I use:
let foo = rawData.read(5) as Int
This works in the simulator, on my iPad Air, and has passed the review for beta testing. However, my external testers have iPad 2s and 4s, and they are getting EXC_ARM_DA_ALIGN errors.
I cannot change the structure of the input file. Is there any way to fix the read function to make sure the objects are built from properly aligned memory locations?
Yes, reading unaligned data can fail on some architectures.
A safe method is to copy the bytes into a (properly aligned) variable.
So the first idea would be to write a generic function:
func read<T>(offset: Int) -> T {
var value : T
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
However, this does not compile, because the variable value
must be initialized before being used, and there is no default
constructor that can be used to initialize a complete generic
variable.
If we restrict the method to types which can be initialized with 0 then we get this:
func read<T : IntegerLiteralConvertible>(offset: Int) -> T {
var value : T = 0
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
This works for all integer and floating point types.
For the general case, one could use the idea from https://stackoverflow.com/a/24335355/1187415:
func read<T>(offset: Int) -> T {
// Allocate space:
let ptr = UnsafeMutablePointer<T>.alloc(1)
// Copy data:
memcpy(ptr, data.bytes + offset, UInt(sizeof(T)))
// Retrieve the value as a new variable:
var item = ptr.move()
// Free the allocated space
ptr.dealloc(1)
return item
}
Swift allows to overload functions with different return types,
therefore you can actually define both methods, and the compiler will
automatically choose the more restrictive one.
FOR ALL SWIFT DEVELOPERS THAT READ THIS
I had a different case with the same crash type!
If your project is defined for (old?) swift version, but you link against a cocoa pod (in my case) that has a different (newer?) swift version in build settings - you’re going to get that crash even when you just trying to set a value of a public field in a regular swift struct.
The stack trace will tell you nothing and may show you the wrong place (CAAnimation free memory for example)
In my case my project was in Swift 4, and my pod (SwiftMessages) was Swift 4.2
AND BOOM!!!
Happy coding!
Related
I went through this Question but the provided solution didn't work. Can someone please explain any alternative approach or proper implementation using os_unfair_lock()?
when I am using 'OS_UNFAIR_LOCK_INIT', it seems unavailable.
Thanks!
In iOS 16 (and macOS 13) and later, you should use OSAllocatedUnfairLock. As the documentation says:
it’s unsafe to use os_unfair_lock from Swift because it’s a value type and, therefore, doesn’t have a stable memory address. That means when you call os_unfair_lock_lock or os_unfair_lock_unlock and pass a lock object using the & operator, the system may lock or unlock the wrong object.
Instead, use OSAllocatedUnfairLock, which avoids that pitfall because it doesn’t function as a value type, despite being a structure. All copied instances of an OSAllocatedUnfairLock control the same underlying lock allocation.
So, if you have a counter that you want to interact with in a thread-safe manner:
import os.lock
let counter = OSAllocatedUnfairLock(initialState: 0)
...
counter.withLock { value in
value += 1
}
...
counter.withLock { value in
print(value)
}
For support of earlier OS versions, see my original answer below.
In Concurrent Programming With GCD in Swift 3, they warn us that we cannot use os_unfair_lock directly in Swift because “Swift assumes that anything that is struct can be moved, and that doesn't work with a mutex or with a lock.”
In that video, the speaker suggests that if you must use os_unfair_lock, that you put this in an Objective-C class (which won't move the struct). Or if you look at some of the stdlib code, they show you can stay in Swift, but use a UnsafeMutablePointer instead of the struct directly. (Thanks to bscothern for confirming this pattern.)
So, for example, you can write an UnfairLock class that avoids this problem:
final class UnfairLock: NSLocking {
private let unfairLock: UnsafeMutablePointer<os_unfair_lock> = {
let pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
pointer.initialize(to: os_unfair_lock())
return pointer
}()
deinit {
unfairLock.deinitialize(count: 1)
unfairLock.deallocate()
}
func lock() {
os_unfair_lock_lock(unfairLock)
}
func tryLock() -> Bool {
os_unfair_lock_trylock(unfairLock)
}
func unlock() {
os_unfair_lock_unlock(unfairLock)
}
}
Then you can do things like:
let lock = UnfairLock()
And then use lock and unlock like you would with NSLock, but using the more efficient os_unfair_lock behind the scenes:
lock.lock()
// critical section here
lock.unlock()
And because this conforms to NSLocking, you can use extensions designed for that. E.g., here is a common method that we use to guarantee that our locks and unlocks are balanced:
extension NSLocking {
func synchronized<T>(block: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try block()
}
}
And
lock.synchronized {
// critical section here
}
But, bottom line, do not use os_unfair_lock from Swift without something like the above or as contemplated in that video, both of which provide a stable memory address for the lock.
You can use os_unfair_lock as below,
var unfairLock = os_unfair_lock_s()
os_unfair_lock_lock(&unfairLock)
os_unfair_lock_unlock(&unfairLock)
This is a fairly simple issue, but one I would like to solve, as it MAY help with performance.
I want to find out if Swift has a way to create a Dictionary, specifying ONLY keys, and maybe no values, or a single value that is set in each entry.
In other words, I want to create a Dictionary object, and "preload" its keys. Since this is Swift, the values could be 0 or nil (or whatever is a default empty).
The reason for this, is so that I can avoid two loops, where I go through once, filling a Dictionary with keys and empty values, and a second one, where I then set those values (There's a practical reason for wanting this, which is a bit out of the scope of this question).
Here's sort of what I'm thinking:
func gimme_a_new_dictionary(_ inKeyArray:[Int]) -> [Int:Int] {
var ret:[Int:Int] = [:]
for key in inKeyArray {
ret[key] = 0
}
return ret
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
But I'm wondering if there's a quicker way to do the same thing (as in "language construct" way -I could probably figure out a faster way to do this in a function).
UPDATE: The first solution ALMOST works. It works fine in Mac/iOS. However, the Linux version of Swift 3 doesn't seem to have the uniqueKeysWithValues initializer, which is annoying.
func gimme_a_new_dictionary(_ inKeyArray:[Int]) -> [Int:Int] {
return Dictionary<Int,Int>(uniqueKeysWithValues: inKeyArray.map {($0, 0)})
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
For Swift 4, you can use the dictionary constructor that takes a sequence and use map to create the sequence of tuples from your array of keys:
let dict = Dictionary(uniqueKeysWithValues: [4,6,1,3,0,1000].map {($0, 0)})
I presume you could optimize your code in terms of allocation by specifying the minimum capacity during the initialization. However, one liner may be the above answer, it's essentially allocation and looping to add 0 in each position.
func gimme_a_new_dictionary(_ inKeyArray:[Int], minCapacity: Int) -> [Int:Int] {
var ret = Dictionray<Int, Int>(minimumCapacity: minCapacity)
for key in inKeyArray {
ret[key] = 0
}
return ret
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
Take a look at this official documentation:
/// Use this initializer to avoid intermediate reallocations when you know
/// how many key-value pairs you are adding to a dictionary. The actual
/// capacity of the created dictionary is the smallest power of 2 that
/// is greater than or equal to `minimumCapacity`.
///
/// - Parameter minimumCapacity: The minimum number of key-value pairs to
/// allocate buffer for in the new dictionary.
public init(minimumCapacity: Int)
I'm trying to convert a lua bridge from Swift 2 to Swift 3. I am not the original author so there are aspects of the library I don't know very well and the original author seems not interested to continue working on the project. I have most of the conversion done but there remain one place I'm stuck and could not figure out. I've tried searching on SO and on the Internet but could not find anything that could help me solve the problem.
If anyone is interested in looking at the full source code, here is my fork of the project on github: https://github.com/weyhan/lua4swift (My changes is in the Swift3 branch)
Allow me setup the context to the error I'm stuck on. There is a Userdata class, specifically in the method userdataPointer<T>() -> UnsafeMutablePointer<T> the c function lua_touserdata returns the block address of userdata as a void * pointer type.
Original code written in Swift 2:
public class Userdata: StoredValue {
public func userdataPointer<T>() -> UnsafeMutablePointer<T> {
push(vm)
let ptr = lua_touserdata(vm.vm, -1)
vm.pop()
return UnsafeMutablePointer<T>(ptr)
}
public func toCustomType<T: CustomTypeInstance>() -> T {
return userdataPointer().memory
}
public func toAny() -> Any {
return userdataPointer().memory
}
override public func kind() -> Kind { return .Userdata }
}
After the conversion with Xcode 8 migration tool, Xcode is complaining about the return line with error Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)':
return UnsafeMutablePointer<T>(ptr)
I've fixed it with:
return (ptr?.assumingMemoryBound(to: T.self))!
Following that above change, now Xcode 8 is now complaining about the calling statement in createCustomType:
public func createCustomType<T: CustomTypeInstance>(setup: (CustomType<T>) -> Void) -> CustomType<T> {
lua_createtable(vm, 0, 0)
let lib = CustomType<T>(self)
pop()
setup(lib)
registry[T.luaTypeName()] = lib
lib.becomeMetatableFor(lib)
lib["__index"] = lib
lib["__name"] = T.luaTypeName()
let gc = lib.gc
lib["__gc"] = createFunction([CustomType<T>.arg]) { args in
let ud = args.userdata
// ******* Here's the line that is causing problem in Swift 3
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
// *******
let o: T = ud.toCustomType()
gc?(o)
return .Nothing
}
if let eq = lib.eq {
lib["__eq"] = createFunction([CustomType<T>.arg, CustomType<T>.arg]) { args in
let a: T = args.customType()
let b: T = args.customType()
return .Value(eq(a, b))
}
}
return lib
}
Where I'm getting stuck is the line :
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
I believe the original author is attempting to clear the memory block where the pointer returned by userdataPointer() call is pointing to.
With the Xcode 8 auto migration tool the above line is converted as below:
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
However Xcode now is then complains that Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer'.
From my research, the change to the return line in userdataPointer seems correct, so I think the issue is with the cast to UnsafeMutableRawPointer. I've tried dropping the cast to UnsafeMutableRawPointer and invoke ud.userdataPointer().deinitialize() directly but I get this error Generic parameter 'T' could not be inferred.
Other things I've tried is to convert the UnsafeMutablePointer to UnsafeMutableRawPointer but It always result in Xcode 8 complaining one thing or another. Any suggestion on how to get this to work?
As you may have already found out, Swift 3 attempts to provide better type safety when it comes to pointers. UnsafeMutablePointer can now only represent a pointer to an instance of a known type. In Swift 2, a C void * was represented by UnsafeMutablePointer<Void>, allowing void and non-void pointers to be treated in the same way, including trying to call a de-initializer of the pointed-to type, which is what the destroy() method in the problematic line of code does:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
In Swift 3 the de-initializer on the pointee is called using the deinitialize() method of the UnsafeMutablePointer structure. It appears that the migration assistant got confused. The line
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
makes little sense because (1) UnsafeMutablePointer cannot be converted using as to UnsafeMutableRawPointer;
(2) UnsafeMutableRawPointer has not deinitialize() method. In Swift 3, UnsafeMutableRawPointer is a special type to represent void*. It is actually quite understandable why the migration tool made this mistake: it blindly replaced destroy() with deinitialize() and UnsafeMutablePointer<Void> with the corresponding Swift 3 type UnsafeMutableRawPointer, without realizing that the conversion would not work.
I don't quite understand why calling destroy() on a void pointer would work in Swift 2. Maybe this was a bug in the program or some compiler trick allowed the correct de-initializer to be called. Without knowing enough about the code, I can't be more specific than to suggest analyzing it to figure out what is the type pointed to by that pointer on which destroy() was called. For example, if we know for sure that it is always the placeholder type T used on the following line:
let o: T = ud.toCustomType()
then the offending line simply becomes
(ud.userdataPointer() as UnsafeMutablePointer<T>).deinitialize()
We need the conversion in the parentheses to allow the compiler to infer the generic parameter.
Thank you for bringing up an interesting problem. BTW, once you get over this obstacle, you are likely to run into other problems. One thing that jumps out is that UnsafeMutablePointer has no .memory in Swift 3; you'll have to use .pointee instead.
Here's an update. After playing with Swift 2.2 on Linux, I realize that calling destroy() on an UnsafeMutablePointer<A> cast as UnsafeMutablePointer<Void> won't call A's deinitializer, even if it has one. So, you have to be careful with that line...
Try creating an instance of UnsafeMutableRawPointer instead of trying to cast it:
UnsafeMutableRawPointer<T>(ud.userdataPointer()).destroy()
I'm getting the following error on simulator iphone6 and above.
Multiple methods named 'intValue' found with mismatched result,
parameter type or attributes
on simulator 5 and below, there's no error.
Offending code is
int destinationType = [[args objectForKey:#"destinationType"] intValue];
I suspect it's due to the swift extension I added
extension NSNull {
func intValue() -> Int {
return 0
}
}
So should I be worried about that the code won't compile on simulator 6 and above?
** EDIT **
It seems the difference is coming from the fact that iPhone 5 and less are 32bit and iPhone5s and above are 64bit.
So I should return more precise type than Int which can be either int32 or int64.
Now my code reads as following and wonder if its the right solution
func intValue() -> Int32 {
return 0
}
The Objective-C method is expecting a C int. But a Swift Int is not a C int. Thus, specifying Int32 is right, because that is the same as int, and also because it is what other implementations of intValue return.
Of course, this brings up the fact that the method name intValue is already in use within Objective-C. Objective-C has no overloading, so if you are going to pick this name, you must match the existing signature (as you are now doing).
Is there a way to increase execution speed of a playground?
I want to iterate many cycles and not to wait 10 minutes.
For example:
import UIKit
var count = 0
for var i = 0; i < 1000000000; i++ {
count++
}
This code will execute a way too long. But I want to get quick result.
One of the biggest performance killer is the output at the right side of the playground. Now I will show you how to minimize this output.
See at the end for your example code.
Best Performance
The most performant way is to make all the performance critical code in a .swift file inside the Sources folder in the playground.
Note: In order to use the functions, classes, properties and methods from the Sources folder you have to mark them public. If you want to subclass a class it has to be marked open.
Good Performance but ugly code
The following method (I think this is not official/intended) can be used to disable the playground output but also leads to ugly code. However it is good for temporary disabling the output.
There are two main ways (and two tricks) to achieve the minimum amount of output (If you find a better way let us know):
Use parenthesis around Void (or Void?) expressions like assignments (normally leads to no output, see also 3.).
var x = 0 // output: 0
(x = 1) // NO output
(x = 2 * x - 1) // NO output
(x.negate()) // NO output
Note: In Swift an assignment returns Void and in case of optional chaining it is Void?.
var x: (Int, Int)? = nil
if (x?.0 = 0) != nil {
// assignment was successful (x!=0 and now x=(0, x.1))
} else {
// assignment was not successful (x==nil)
}
Initialize and declare variables separately.
var x: Int // NO output
(x = 0) // NO output
If 1. does not work add an additional no-op (no operation) line above or below ().
This happens in single line closures (and probably in some other contexts) for example: (see also the code below)
[1, 4, 5, 6].mmap{
() // without this line the line below would yield to an output
($1 = $0 + 1)
} as [Int]
Instead of wrapping every line in parenthesis you can also use a tuple of all the expressions which is then assigned to a variable:
var a: Any // this may be a useful definition in this context
var x: Int
var y: Int
(a = (x = 0,
y = 1,
x = y + 1,
y = x*x))
However this could lead to a indentation disaster...
Where it does not work (I've found no way how to remove the output; This list is probably not complete):
returns in functions and closures
Declaration of Optional variables e.g.: var x: Int?
An example of a new map method on Sequence
Usage: See above at Point 3.
The signature of Sequence.map is
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
Since I have not found a way how to remove the output of returns one can use a closure with an inout argument (get the "return" value with an assignment). A possible signature could then be:
func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]
so we can pass nil in the inout argument since it is a good default for every possible U without imposing a constraint on U which could require an instance generator (e.g.: init() { ... }).
Unfortunately Swfit has a hard time to infer U so you would need to help the compiler with explicit type annotations. In addition var newElement: U? does return nil in the sidebar.
Now I will use Any instead of U?:
extension Sequence {
// ATTENTION: this is not as performant as the normal `map`!
func mmap<U>(transform: (Element, inout Any) -> ()) -> [U] {
var result: [U]
(result = [U]())
for element in self {
var newElement: Any
(newElement = 0) // some placeholder element
(transform(element, &newElement))
// assume the inout element to be of type `U`
(result.append(newElement as! U))
}
return result // the ONLY output in this method
}
}
Your example code
Using Swift 4
var count = 0
for i in 0..<1_000_000_000 {
(count += 1)
if count % 100_000 == 0 {
// print only every 100_000th loop iteration
print(count)
}
}
Without the parenthesis: about 10.000 loop iterations per second
With parenthesis: about 10.000.000 loop iterations per second !!!
I feel your pain, I was playing around with printing 2D functions to [Double] then converting to UIImageView. One of the steps was iterating over millions of pixels, and it took forever.
Anything computationally intensive, or repetitive, or potentially time consuming should be put in the "Sources" folder of the playground. That way the code is precompiled before your playground is run. Put the output of that for loop in a public function that you can call from the playground. Then you won't have to sit there watching the playground count all the times it went through the for loop.
I had a such problem and I have solved it after days of trials. All I needed to do is move all my code in folder Sources of playground. So, after that the execution speed was enhanced.
I hope it helps you.
Note: don't forget to use open classes.
To speed up the build in Xcode Playground and prevent the loading icon to keep spinning forever:
go to the sidebar on the right, and change iOS to macOS in Playground Settings
instead of importing UIKit, import Foundation
(this would work if you're not trying to use specific stuff from the UIKit framework)