Usage of withMemoryRebound with Apples Swift 3 beta 6
Pointer conversions are much more "verbose" now since Xcode 8 beta 6.
Here is a possible solution:
func binarytotype <T> (_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
UnsafeRawPointer($0.baseAddress!).load(as: T.self)
}
}
func typetobinary<T>(_ value: T) -> [UInt8] {
var data = [UInt8](repeating: 0, count: MemoryLayout<T>.size)
data.withUnsafeMutableBufferPointer {
UnsafeMutableRawPointer($0.baseAddress!).storeBytes(of: value, as: T.self)
}
return data
}
Example:
let d = typetobinary(UInt16(1000))
print(d) // [232, 3]
let i = binarytotype(d, UInt16.self)
print(i) // 1000
See SE-0107 UnsafeRawPointer API for
detailed information about the new raw pointer API.
Swift 3 UnsafePointer($0) no longer compile in Xcode 8 beta 6
From the Release Notes of Xcode 8 beta 6:
- An
Unsafe[Mutable]RawPointer
type has been introduced, replacingUnsafe[Mutable]Pointer<Void>
. Conversion fromUnsafePointer<T>
to
UnsafePointer<U>
has been disallowed.Unsafe[Mutable]RawPointer
provides an API for untyped memory access, and an API for binding
memory to a type. Binding memory allows for safe conversion between
pointer types. SeebindMemory(to:capacity:)
,assumingMemoryBound(to:)
,
andwithMemoryRebound(to:capacity:)
. (SE-0107)
In your case, you may need to write something like this:
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
UnsafePointer no longer works in swift 3
You can try this:
let rawPointer = UnsafeRawPointer(array1)
let pointer = rawPointer.assumingMemoryBound(to: UInt32.self)
let value = pointer.pointee
Raw pointer is a pointer for accessing untype data.
assumingMemoryBound(to:)
can convert from an UnsafeRawPointer
to UnsafePointer<T>
.
Reference :Swift 3.0 Unsafe World
Fatal error when using withMemoryRebound in iOS/Swift
Your original array arr
is an array of Float
s
var arr = Array<Float>(repeating: 0, count: 163840)
but you're trying to bind the pointer to a UInt16
arr_pointer.withMemoryRebound(to: UInt16.self)
Xcode 8 beta 6: main.swift won't compile
I write it this way:
UIApplicationMain(
CommandLine.argc,
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(
to: UnsafeMutablePointer<Int8>.self,
capacity: Int(CommandLine.argc)),
nil,
NSStringFromClass(AppDelegate.self)
)
To change the UIApplication class, substitute NSStringFromClass(MobileUIApplication.self)
for nil
in that formulation.
However, if your only purpose here is to substitute a UIApplication subclass as the shared application instance, there's an easier way: in the Info.plist, add the "Principal class" key and set its value to the string name of your UIApplication subclass, and mark your declaration of that subclass with an @objc(...)
attribute giving it the same Objective-C name.
EDIT This problem is now solved in Swift 4.2. CommandLine.unsafeArgv
now has the correct signature, and one can call UIApplicationMain
easily:
UIApplicationMain(
CommandLine.argc, CommandLine.unsafeArgv,
nil, NSStringFromClass(AppDelegate.self)
)
SwiftData (SQLite wrapper) broken with Swift 3.0
sqlite3_column_int(statement, index)
returns an Int32
and
sqlite3_column_int(statement, index) != 0
is a boolean value, so that makes no sense as the return value if
an (optional) AnyObject
is expected. You can wrap the integer into
a NSNumber
instead:
func getColumnValue(_ statement: OpaquePointer, index: Int32, type: String) -> AnyObject? {
let val = sqlite3_column_int(statement, index)
return NSNumber(value: val)
}
Another option would be
func getColumnValue(_ statement: OpaquePointer, index: Int32, type: String) -> AnyObject? {
return sqlite3_column_int(statement, index) as AnyObject
}
because in Swift 3, anything can be converted to AnyObject
.
The difference is that in the second solution, the object can only be
converted back to the original number type Int32
, but not toInt
or any other integer type.
For the other problems, see
- Issue with UnsafePointer<Uint8> in SQLite project in Swift
- Error in for loop CGFloat
Getting memory usage Live/Dirty Bytes in iOS app programmatically (not Resident/Real Bytes)
I found something else, but it seems to work on the device that the previous method didn't work and not work on the device that the previous method did work :-(
Now I need to figure out how to know which one to use. One device is iPhone 5s with iOS 9 and another is iPhone 5s with iOS 11.
I guess I need to test on more veriaty of devices...
I found it here:
https://opensource.apple.com/source/WebKit/WebKit-7603.1.30.1.33/ios/Misc/MemoryMeasure.mm.auto.html
This translated to something like this in Objective-C:
task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t err = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if (err != KERN_SUCCESS)
return 0;
NSLog(@"Memory in use vmInfo.internal (in bytes): %u", vmInfo.internal);
return vmInfo.internal;
I think if I add vmInfo.internal and vmInfo.compressed then I'll get the right result (matching what Xcode Debug navigator is showing)
It looks right for these two devices so far, and 2 other devices I tested.
So my final code looks like this:
task_vm_info_data_t info;
mach_msg_type_number_t size = TASK_VM_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(),
TASK_VM_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
mach_vm_size_t totalSize = info.internal + info.compressed;
NSLog(@"Memory in use (in bytes): %u", totalSize);
return totalSize;
} else {
NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
How to use SCNetworkReachability in Swift
(This answer was extended repeatedly due to changes in the Swift language, which made it a bit confusing. I have now rewritten it and removed everything which refers to Swift 1.x. The older code can
be found in the edit history if somebody needs it.)
This is how you would do it in Swift 2.0 (Xcode 7):
import SystemConfiguration
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(&zeroAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else {
return false
}
var flags : SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.Reachable)
let needsConnection = flags.contains(.ConnectionRequired)
return (isReachable && !needsConnection)
}
Explanations:
As of Swift 1.2 (Xcode 6.3), imported C structs have a default initializer in Swift, which initializes all of the struct's fields to zero, so the socket address structure can be initialized with
var zeroAddress = sockaddr_in()
sizeofValue()
gives the size of this structure, this has
to be converted toUInt8
forsin_len
:zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
AF_INET
is anInt32
, this has to be converted to the correct type forsin_family
:zeroAddress.sin_family = sa_family_t(AF_INET)
withUnsafePointer(&zeroAddress) { ... }
passes the address of the
structure to the closure where it is used as argument forSCNetworkReachabilityCreateWithAddress()
. TheUnsafePointer($0)
conversion is needed because that function expects a pointer tosockaddr
, notsockaddr_in
.The value returned from
withUnsafePointer()
is the return value
fromSCNetworkReachabilityCreateWithAddress()
and that has the
typeSCNetworkReachability?
, i.e. it is an optional.
Theguard let
statement (a new feature in Swift 2.0) assigns the unwrapped value to thedefaultRouteReachability
variable if it is
notnil
. Otherwise theelse
block is executed and the function
returns.- As of Swift 2,
SCNetworkReachabilityCreateWithAddress()
returns
a managed object. You don't have to release it explicitly. As of Swift 2,
SCNetworkReachabilityFlags
conforms toOptionSetType
which has a set-like interface. You create an
empty flags variable withvar flags : SCNetworkReachabilityFlags = []
and check for flags with
let isReachable = flags.contains(.Reachable)
let needsConnection = flags.contains(.ConnectionRequired)The second parameter of
SCNetworkReachabilityGetFlags
has the typeUnsafeMutablePointer<SCNetworkReachabilityFlags>
, which means that you have to
pass the address of the flags variable.
Note also that registering a notifier callback is possible as of
Swift 2, compare Working with C APIs from Swift and Swift 2 - UnsafeMutablePointer<Void> to object.
Update for Swift 3/4:
Unsafe pointers cannot be simply be converted to a pointer of a
different type anymore (see - SE-0107 UnsafeRawPointer API). Here the updated code:
import SystemConfiguration
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
Trying to stream audio from microphone to another phone via multipeer connectivity
Your AVAudioPCMBuffer
serialisation/deserialisation is wrong.
Swift3's casting has changed a lot & seems to require more copying than Swift2.
Here's how you can convert between [UInt8]
and AVAudioPCMBuffer
s:
N.B: this code assumes mono float data at 44.1kHz.
You might want to change that.
func copyAudioBufferBytes(_ audioBuffer: AVAudioPCMBuffer) -> [UInt8] {
let srcLeft = audioBuffer.floatChannelData![0]
let bytesPerFrame = audioBuffer.format.streamDescription.pointee.mBytesPerFrame
let numBytes = Int(bytesPerFrame * audioBuffer.frameLength)
// initialize bytes to 0 (how to avoid?)
var audioByteArray = [UInt8](repeating: 0, count: numBytes)
// copy data from buffer
srcLeft.withMemoryRebound(to: UInt8.self, capacity: numBytes) { srcByteData in
audioByteArray.withUnsafeMutableBufferPointer {
$0.baseAddress!.initialize(from: srcByteData, count: numBytes)
}
}
return audioByteArray
}
func bytesToAudioBuffer(_ buf: [UInt8]) -> AVAudioPCMBuffer {
// format assumption! make this part of your protocol?
let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)
let frameLength = UInt32(buf.count) / fmt.streamDescription.pointee.mBytesPerFrame
let audioBuffer = AVAudioPCMBuffer(pcmFormat: fmt, frameCapacity: frameLength)
audioBuffer.frameLength = frameLength
let dstLeft = audioBuffer.floatChannelData![0]
// for stereo
// let dstRight = audioBuffer.floatChannelData![1]
buf.withUnsafeBufferPointer {
let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: Float.self, capacity: Int(frameLength))
dstLeft.initialize(from: src, count: Int(frameLength))
}
return audioBuffer
}
Related Topics
"Message from Debugger: Unable to Attach" When Running Tests on Osx App
Swift. Is the (Absolutely) Sole Specific Advantage of Unowned Over Weak, Performance
Create Complicated Nscompoundpredicate in Swift 3
Why Mark Something Final in Swift Except for Architectural Considerations
Why Does Somestruct() Is Anyobject Return True
Swiftui - Show the Data Fetched from Firebase in View
Decode Dictionary with Random Initial Key
Firebase Storage Overwriting Files
Round Currency Closest to Five
Swift - Kvo - Change.Newvalue and Change.Oldvalue Are Nil
Same Class Extension in Two Different Modules
Can You Enforce a Typealias in Swift
Saving Dictionary into Nsuserdefaults
Displaying State of an Async API Call in Swiftui
Swift Skshapenode Shapewithsplinepoints
Swiftui [Bug] Navigationview and List Not Showing on iPad Simulator Only