Will this static var work like C? - ios

I want to define a static variable on a class using Swift 2 that is a NSLock.
After researching I discovered that I have to use a struct, in something like this:
class Entity: NSManagedObject {
struct Mechanism {
static let lock = NSLock()
}
func myFunction -> NSArray {
Mechanism.lock.lock()
// do something
Mechanism.lock.unlock()
}
}
Will this work like C? I mean, the first time Mechanism is used a static lock constant will be created and subsequent calls will use the same constant?
I feel that this is not correct because the line
static let lock = NSLock()
is initializing a NSLock. So it will initialize a new one every time.
If this was not swift I would do like this:
static NSLock *lock;
if (!lock) {
lock = ... initialize
}
How do I do the equivalent in Swift 2?

You said that "after researching, I discovered that I have to use a struct [to get a static]." You then go on to ask whether it really is a static a how it changes in Swift 2.0.
So, a couple of observations:
Yes, this static within a struct pattern will achieve the desired behavior, that only one NSLock will be instantiated.
The significant change in the language was in Swift 1.2 (not 2.0), which now allows static variables, eliminating the need for the struct altogether:
class Entity: NSManagedObject {
static let lock = NSLock()
func myFunction() -> NSArray {
Entity.lock.lock()
// do something
Entity.lock.unlock()
}
}

Seriously, nobody uses NSLock on MacOS X or iOS. In Objective C, you use #synchronized. In Swift, you use a global function like this:
func Synchronized (obj: AnyObject, _ block: dispatch_block_t)
{
objc_sync_enter (obj)
block ()
objc_sync_exit (obj)
}
First, this uses a recursive lock. That alone will safe you gazillions of headaches. Second, it works much more fine grained, with a lock for one specific object. To use:
func myFunction() -> NSArray {
Synchronized(someObject) {
// Stuff to do.
}
}

Related

What is the reason behind objc_sync_enter doesn't work well with struct, but works well with class?

I have the following demo code.
struct IdGenerator {
private var lastId: Int64
private var set: Set<Int64> = []
init() {
self.lastId = 0
}
mutating func nextId() -> Int64 {
objc_sync_enter(self)
defer {
objc_sync_exit(self)
}
repeat {
lastId = lastId + 1
} while set.contains(lastId)
precondition(lastId > 0)
let (inserted, _) = set.insert(lastId)
precondition(inserted)
return lastId
}
}
var idGenerator = IdGenerator()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func click(_ sender: Any) {
DispatchQueue.global(qos: .userInitiated).async {
for i in 1...10000 {
let id = idGenerator.nextId()
print("i : \(id)")
}
}
DispatchQueue.global(qos: .userInitiated).async {
for j in 1...10000 {
let id = idGenerator.nextId()
print("j : \(id)")
}
}
}
}
Whenever I execute click, I would get the following crash
Thread 5 Queue : com.apple.root.user-initiated-qos (concurrent)
#0 0x000000018f58b434 in _NativeSet.insertNew(_:at:isUnique:) ()
#1 0x000000018f598d10 in Set._Variant.insert(_:) ()
#2 0x00000001001fe31c in IdGenerator.nextId() at /Users/yccheok/Desktop/xxxx/xxxx/ViewController.swift:30
#3 0x00000001001fed8c in closure #2 in ViewController.click(_:) at /Users/yccheok/Desktop/xxxx/xxxx/ViewController.swift:56
It isn't clear why the crash happen. My raw guess is, under struct, objc_sync_enter(self) doesn't work as expected. 2 threads accessing Set simultaneously will cause such an issue.
If I change the struct to class, everything just work fine.
class IdGenerator {
private var lastId: Int64
private var set: Set<Int64> = []
init() {
self.lastId = 0
}
func nextId() -> Int64 {
objc_sync_enter(self)
defer {
objc_sync_exit(self)
}
repeat {
lastId = lastId + 1
} while set.contains(lastId)
precondition(lastId > 0)
let (inserted, _) = set.insert(lastId)
precondition(inserted)
return lastId
}
}
May I know what is the reason behind? Why the above objc_sync_enter works well in class, but not in struct?
The objc_sync_enter/objc_sync_exit functions take an object instance and use its identity (i.e., address in memory) in order to allocate and associate a lock in memory — and use that lock to protect the code between the enter and exit calls.
However, structs are not objects, and don't have reference semantics which would allow them to be used in this way — they're not even guaranteed to be allocated in a stable location in memory. However, to support interoperation with Objective-C, structs must have a consistent object-like representation when used from Objective-C, or else calling Objective-C code with, say, a struct inside of an Any instance could trigger undefined behavior.
When a struct is passed to Objective-C in the guise of an object (e.g., inside of Any, or AnyObject), it is wrapped up in a temporary object of a private class type called __SwiftValue. This allows it to look like an object to Objective-C, and in some cases, be used like an object, but critically, it is not a long-lived, stable object.
You can see this with the following code:
struct Foo {}
let f = Foo()
print(f) // => Foo()
print(f as AnyObject) // => __SwiftValue
print(ObjectIdentifier(f as AnyObject)) // => ObjectIdentifier(0x0000600002595900)
print(ObjectIdentifier(f as AnyObject)) // => ObjectIdentifier(0x0000600002595c60)
The pointers will change run to run, but you can see that every time f is accessed as an AnyObject, it will have a new address.
This means that when you call objc_sync_enter on a struct, a new __SwiftValue object will be created to wrap your struct, and that object is passed in to objc_sync_enter. objc_sync_enter will then associate a new lock with the temporary object value which was automatically created for you... and then that object is immediately deallocated. This means two major things:
When you call objc_sync_exit, a new object will be created and passed in, but the runtime has no lock associated with that new object instance! It may crash at this point.
Every time you call objc_sync_enter, you're creating a new, separate lock... which means that there's effectively no synchronization at all: every thread is getting a new lock altogether.
This new pointer instance isn't guaranteed — depending on optimization, the object may live long enough to be reused across objc_sync_* calls, or a new object could be allocated exactly in the same place as an old one... or a new object could be allocated where a different struct used to be, and you accidentally unlock a different thread...
All of this means that you should definitely avoid using objc_sync_enter/objc_sync_exit as a locking mechanism from Swift, and switch over to something like NSLock, an allocated os_unfair_lock, or even a DispatchQueue, which are well-supported from Swift. (Really, the objc_sync_* functions are primitives for use largely by the Obj-C runtime only, and probably should be un-exposed to Swift.)

Memory Leak Kotlin Native library in iOS

I'm building a Kotlin library to use in my iOS app using Kotlin/Native. After I call some methods in the library from Swift, which works, I also want to call methods in Swift from the library. To accomplish this I implemented an interface in the library:
class Outbound {
interface HostInterfaceForTracking {
fun calcFeatureVector(bitmap: Any?): Array<Array<FloatArray>>?
}
var hostInterface: HostInterfaceForTracking? = null
fun registerInterface(hostInterface: HostInterfaceForTracking) {
this.hostInterface = hostInterface
instance.hostInterface = hostInterface
}
}
This is implemented on the Swift side like this:
class HostInterfaceForTracking : OutboundHostInterfaceForTracking {
var t : Outbound? = nil
init() {
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
}
func calcFeatureVector(bitmap: Any?) -> KotlinArray<KotlinArray<KotlinFloatArray>>? {
do {
var test : Any? = (bitmap as! Bitmap).bitmap
return nil
} catch {
return nil
}
}
}
The TrackingWrapper looks like this:
class TrackingWrapper : NSObject {
static var instance: TrackingWrapper? = nil
var inbound: Inbound? = nil
var worker: Worker
override init() {
self.worker = Worker()
super.init()
initInboundInterface()
}
func initInboundInterface() {
runOnMatchingLibraryThread {
TrackingWrapper.instance = self
self.inbound = Inbound()
HostInterfaceForTracking()
}
}
func runOnMatchingLibraryThread(block: #escaping() -> Void) {
worker.enqueue {
block()
}
}
}
The function runOnMatchingLibraryThread is needed because every call to the TrackingLibrary needs to be called from the exact same thread, so the Worker class initializes a thread and enqueues every method to that thread.
The Bitmap in this case is simply a wrapper for an UIImage, which I already accessed with the .bitmap call, so I've tried to access the wrapped UIImage and save it in the test variable. The library gets the current camera frame from the Swift side every few frames and sends the current image wrapped as a Bitmap to the method calcFeatureVector depicted here.
Problem: My memory load starts increasing as soon as the app starts until the point it crashes. This is not the case if I don't access the wrapped UIImage (var test : Any? = (bitmap as! Bitmap)). So there is a huge memory leak, just by accessing the wrapped variable on the Swift side. Is there anything I've missed or is there any way to release the memory?
Looks like you have a circular dependency here:
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
You are asking a property inside HostInterfaceForTracking to maintain a strong reference to the same instance of HostInterfaceForTracking. You should be using [weak self] to avoid the circular reference.
EDIT:
Ok after seeing the rest of you code theres a lot to unpack. There is a lot of unnecessary bouncing back and forth between classes, functions and threads.
There is no need to use runOnMatchingLibraryThread to just create an instance of something. You only need to use that for the code processing the image itself (I would assume, I haven't seen anything so far that requires being split off into another thread). Inside TrackingWrapper, you can create a singleton more easily, and matching the swift pattern by simply doing this as the first line:
static let shared = TrackingWrapper()
And everywhere you want to use it, you can just call TrackingWrapper.shared. This is more common and will avoid one of the levels of indirection in the code.
I'm not sure what Worker or Inbound are, but again these can and should be created inside the TrackingWrapper init, rather than branching Inbound's init, to use another thread.
Inside initInboundInterface you are creating an instance of HostInterfaceForTracking() which doesn't get stored anywhere. The only reason HostInterfaceForTracking is continuing to stay in memory after its creation, is because of the internal circular dependency inside it. This is 100% causing some form of a memory issue for you. This should probably also be a property on TrackingWrapper, and again, its Init should not be called inside runOnMatchingLibraryThread.
Having HostInterfaceForTracking's init, also using runOnMatchingLibraryThread is problematic. If we inline all the code whats happening is this:
TrackingWrapper
init() {
self.runOnMatchingLibraryThread {
TrackingWrapper.instance = self
self.inbound = Inbound()
TrackingWrapper.instance?.runOnMatchingLibraryThread {
self.t = Outbound()
self.t!.registerInterface(hostInterface: self)
}
}
}
Having all these classes unnecessarily keep coming back to TrackingWrapper is going to cause issues.
Inside HostInterfaceForTracking 's init, no need to be creating Outbound on a separate thread. First line in this class can simply be:
var t : Outbound = OutBound()
Or do it in the init if you prefer. Either way will also remove the issue of needing to unwrap Outbound before using it.
Inside Outbound you are storing 2 references to the hostInterface instance:
this.hostInterface = hostInterface
instance.hostInterface = hostInterface
I would have imagined there should only be 1. If there are now multiple copies of a class that has a circular dependency, which has multiple calls to separate threads. This again will cause issues.
I'm still not sure on the differences between Swift and Kotlin. In Swift when passing self into a function to be stored, the class storing it would mark the property as weak, like so:
weak var hostInterface: ......
Which will avoid any circular dependency from forming. A quick google says this isn't how things work in Kotlin. It might be better to look into the swift side passing in a closure (lambda on kotlin) and the kotlin side executing that. This might avoid the need to store a strong reference. Otherwise you need to be looking into some part of your code setting hostInterface back to null. Again its a bit hard to say only seeing some of the code and not knowing how its working.
In short, it looks like the code is very over complicated, and needs to be simplified, so that all these moving pieces can be tracked easier.

'OSSpinLock' was deprecated in iOS 10.0: Use os_unfair_lock() from <os/lock.h> instead

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)

Swift: Passing callbacks to struct instance

I would like to do something along the lines of the pseudo code below:
struct Foo {
let BarInstance = Bar(Callback: CallBarInstance)
func CallBarInstance() -> Void {
BarInstance.FunctionToCall()
}
}
struct Bar {
var Callback: () -> Void
func FunctionToCall() -> Void {
print("Hello")
}
// More code that calls Callback
}
I get the error that I can't convert (Foo)->()->Void to ()->Void. I think I understand this is because the instance of Foo is being passed in as it is a member function. I figured it could then be made a static function that calls but getting access to the member variables felt hacky - is there a good way to get the functionality I want in Swift?
You seem to be trying to do something dangerous here, and Swift is stopping you from doing it.
In this line:
let BarInstance = Bar(Callback: CallBarInstance)
You are leaking an uninitialised self to Bar. Why? Because at the point in time when Bar.init is called, Foo is not be fully initialised. Namely, what is the value of BarInstance at this point? It is undefined. Yet you are trying to pass self.CallbarInstance to Bar.init!
Imagine what could happen if this were allowed. Bar.init had called the passed in function directly, before it returns. Now we have a very weird situation: CallBarInstance actually makes use of the value of BarInstance in its implementation, but what's the value of BarInstance? Bar.init hasn't returned so it's undefined!
The error message is a bit unclear though. Swift treats CallBarInstance as a (Foo) -> () -> Void in this situation (as if you were calling it as Foo.CallBarInstance), because self is unavailable.
You can kind of fix it by initialising BarInstance with some other value first, then assigning the intended Bar instance, but I don't know whether this will produce your intended behaviour or not.
struct Foo {
var BarInstance = Bar(Callback: {})
init() {
BarInstance = Bar(Callback: CallBarInstance)
}
func CallBarInstance() -> Void {
BarInstance.FunctionToCall()
}
}

How to organize swift source code in pattern?

I have some codes in java which organized well, so it helps me manage source code as well as extend in future easily. These codes as follow
public interface IDataModel<T extends IDataModel> {
void copyData(T data);
long getUpdatedTime();
}
public abstract class AbstractDataModel<T extends IDataModel> implements IDataModel<T>{
protected long updatedTime;
public long getUpdatedTime(){
return updatedTime;
}
}
public class concreteDataA extends AbstractDataModel<concreteDataA>{
String property1;
public String getProperty1(){
return property1;
}
#override
public void copyData(concreteDataA data){
property1 = data.getProperty1();
updatedTime = data.getUpdatedTime();
}
}
Now i want to port into iOS swift 3.0. Is it possible to organize code in swift 3.0 as above? Or is there any equivalent way in swift to organize code as above? I'm quite new to swift iOS, so it makes me hard to organize source code in pattern. Thanks you.
You haven't provided much in the way of context, but it seems like you're struggling developing a "protocol-oriented" solution, as Swift folks like to call the pattern. Here are a couple of options that might solve your problem (spoiler – I think the problem is in your design):
Interface: Protocol, Abstract Class: Protocol Extension
Like #sulthan mentioned, you can certainly get to a similar place using protocols with default implementations, like so:
protocol DataModel {
mutating func copy(data: Self)
var updatedTime : Float { get }
}
extension DataModel {
var updatedTime : Float { return 0 }
}
However, you'll run into a problem when you try to implement the ConcreteDataModel since you want to specialize it to account for the property1 value that isn't mentioned in the protocol. Your options are to relax that requirement in ConcreteDataModel (aka don't do that) or use typecasting. Please note, fighting the typing system in Swift is a sure sign that your code is not idiomatic! You should see this difficulty as the language nudging you to reconsider your approach.
Use immutable data types
This is the most straight-forward answer. If what you've described above is actually a concrete example from your app, then you don't really need protocols at all. (In fact, your Java implementation is certainly over-abstracting.) Swift structs are immutable, which means that whenever you change them, you are actually changing a copy.
struct DataModel {
let updatedTime: Float
mutating func update(time: Float) {
self = DataModel(updatedTime: time)
}
}
var data1 = DataModel(updatedTime: 3)
var data2 = data1
data2.update(time: 17)
print(data1.updatedTime) // 3.0
print(data2.updatedTime) // 17.0
Model your behavior apart from your data
This is the generalized solution. From a design perspective, it's clear that you have two distinct concerns. You want something copyable, and you want something that tracks "time." Why not just let your code reflect that?
protocol Copier {
associatedtype Data
func copy(from: Data) -> Data
}
protocol Clock {
var time: Float { get }
}
class AlarmClock: Clock, Copier {
let time: Float
let alarm: Float
init(time: Float, alarm: Float) {
self.time = time
self.alarm = alarm
}
func copy(from: AlarmClock) -> AlarmClock {
return AlarmClock(time: from.time, alarm: from.alarm)
}
}
Of course, you could even go the last step and provide the default implementation for Clock.time if you really needed it.

Resources