In Swift 3.1, UnsafeMutablePointer.initialize(from:) is deprecated
It is correct, but you can allocate and initialize memory slightly simpler with
let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 64)
pointer.initialize(to: 0, count: 64)
Creating a buffer pointer view can still be useful because that
is a collection, has a count
property and can be enumerated:
let buffer = UnsafeMutableBufferPointer(start: pointer, count: 64)
for byte in buffer {
// ...
}
but that is independent of how the memory is initialized.
Swift 3.1 deprecates initialize(). How can I achieve the same thing?
Easy/Simple Solution
A common app entry point is an application delegate's applicationDidFinishLaunching
. We could simply add a static function to each class that we want to notify on initialization, and call it from here.
This first solution is simple and easy to understand. For most cases, this is what I'd recommend. Although the next solution provides results that are more similar to the original initialize()
function, it also results in slightly longer app start up times. I no longer think
it is worth the effort, performance degradation, or code complexity in most cases. Simple code is good code.
Read on for another option. You may have reason to need it (or perhaps parts of it).
Not So Simple Solution
The first solution doesn't necessarily scale so well. And what if you are building a framework, where you'd like your code to run without anyone needing to call it from the application delegate?
Step One
Define the following Swift code. The purpose is to provide a simple entry point for any class that you would like to imbue with behavior akin to initialize()
- this can now be done simply by conforming to SelfAware
. It also provides a single function to run this behavior for every conforming class.
protocol SelfAware: class {
static func awake()
}
class NothingToSeeHere {
static func harmlessFunction() {
let typeCount = Int(objc_getClassList(nil, 0))
let types = UnsafeMutablePointer<AnyClass>.allocate(capacity: typeCount)
let autoreleasingTypes = AutoreleasingUnsafeMutablePointer<AnyClass>(types)
objc_getClassList(autoreleasingTypes, Int32(typeCount))
for index in 0 ..< typeCount { (types[index] as? SelfAware.Type)?.awake() }
types.deallocate(capacity: typeCount)
}
}
Step Two
That's all good and well, but we still need a way to actually run the function we defined, i.e. NothingToSeeHere.harmlessFunction()
, on application startup. Previously, this answer suggested using the Objective-C code to do this. However, it seems that we can do what we need using only Swift. For macOS or other platforms where UIApplication is not available, a variation of the following will be needed.
extension UIApplication {
private static let runOnce: Void = {
NothingToSeeHere.harmlessFunction()
}()
override open var next: UIResponder? {
// Called before applicationDidFinishLaunching
UIApplication.runOnce
return super.next
}
}
Step Three
We now have an entry point at application startup, and a way to hook into this from classes of your choice. All that is left to do: instead of implementing initialize()
, conform to SelfAware
and implement the defined method, awake()
.
Swift 4.1 deinitialize and deallocate(capacity:) deprecated
Yes, that is part of SE-0184 Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size,
which has been implemented in Swift 4.1.
In particular:
Removing capacity from deallocate(capacity:) will end the confusion over what deallocate() does, making it obvious that deallocate() will free the entire memory block at self, just as if free() were called on it.
The old deallocate(capacity:) method should be marked as deprecated and eventually removed since it currently encourages dangerously incorrect code.
UnsafePointerUInt8 initializer in Swift 3
In Swift 3, you cannot init an
UnsafePointer
using anUnsafeRawPointer
.You can use
assumingMemoryBound(to:)
to convert anUnsafeRawPointer
into anUnsafePointer<T>
. Like this:var ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
Use
debugDescription
ordistance(to:)
to compare two pointer.while(ptr.debugDescription < endPtr.debugDescription)
or
while(ptr.distance(to:endPtr) > 0)
Related Topics
Xcode Error: Ar Reference Image Must Have Non Zero Positive Width
"Ambiguous Use" on Generic Method After Migration to Swift 4
How to Use @Fetchrequest Outside a View
Wait for Download Task to Finish in Nsurlsession
How to Add More Cases for Enum in Swift
Debug View Hierarchy Does Not Render UI
Extend All Number Types in Swift
Nstextfield Non-System-Font Content Clipped When Usessinglelinemode Is True
Flipping The Positions of Items in a UIstackview
iOS 16 Swiftui List Background
Errors Encountered While Discovering Extensions: Error Domain=Pluginkit Code=13 "Query Cancelled"
Location Access Request in iOS 11
Xcode Issue: Library Not Loaded: @Rpath/Libswiftappkit.Dylib
Swift Protocol Extension Implementing Another Protocol with Shared Associated Type
Swift Unable to Locate and Read Property List (.Plist) File
How to Unwrap Optional<Optional<T>> in Swift 1.2
In Swift 5, What Is a Way to Compare Pointers to Two Closures