Store pointer to object in SQLite in Swift - swift

I've a tree of objC/Swift objects. They represent graphical objects, which I want to query based on location and other properties.
Since SQLite supports an RTree table, I store the boundary boxes and relevant properties in tables along side a pointer to the original object. When I retrieve a result I can easily get the original object. This works fine in objC with the following conversions:
pointer to int: (intptr_t)self
int to pointer: (__bridge SomeObject *)(void *)(intptr_t)pointerValue
I'm updating the code and also converting to Swift. Unfortunately I can't find a way to do something equivalent in Swift. I've found withUnsafePointer(), but it states that the pointer is only valid inside the closure. It also doesn't seem to be possible to get the actual pointer value as an Int from UnsafePointer. It only has a hashValue property.
How can I get a pointer in Swift which I can store in SQLite?
Note: The SQLite database is in memory and I can guarantee that the objects will stay around as long as they are 'referenced' from the database. There is no need for any kind of long lived persistence.

You can use Unmanaged. For example (Swift 3):
class MyClass {
let name: String
init(name: String) {
self.name = name
}
}
func makeInt(from obj: MyClass) -> Int {
let unmanaged = Unmanaged.passUnretained(obj)
return Int(bitPattern: unmanaged.toOpaque())
}
func makeObj(from int: Int) -> MyClass? {
guard let pointer = UnsafeRawPointer(bitPattern: int) else {
return nil
}
let unmanaged = Unmanaged<MyClass>.fromOpaque(pointer)
return unmanaged.takeUnretainedValue()
}
let obj = MyClass(name: "foo")
let int = makeInt(from: obj)
if let obj2 = makeObj(from: int) {
print(obj2.name) // "foo"
}
The use of "unretained" values means that no memory management happens: it's your responsibility to keep objects alive.

Related

How to share array memory between JavaScriptCore and Swift?

I am trying to write a Swift program that runs JS via JavaScriptCore. I wish to share memory between both parts of my program such that the JS writes to a typed array buffer created in Swift, and Swift reads and writes to it afterwards. This will be a sort of command buffer.
For example, here is some pseudocode that approximately represents what I'm planning to do:
// js
let buf;
let i = 0;
setup() {
buf = new Uint8Array(mem.alloc(N_BYTES));
}
frame() {
i = 0;
buf[i++] = some_command_enum;
}
// swift
func alloc(bytes : Int) -> the_memory {
// allocate bytes uints and save the memory here
// save a reference to the memory here
// return the memory to use in JS
}
The problem is that whenever I try actually adding the implementation to alloc, JS reports via exception that the function is undefined, meaning that something is off with the way I'm doing things. Non-returning functions are fine, so I have that down.
This is my faulty implementation (please see the comments):
// swift
#objc protocol JSMemoryExports: JSExport {
static func alloc(_ byte_count: Int) -> JSObjectRef
static func free(_ memory: JSObjectRef)
}
class JSMemory: NSObject, JSMemoryExports {
// What is the correct return type?
class func alloc(_ byte_count: Int) -> JSObjectRef {
// temp
let jsContext = JS_Controller.js.ctx!
print("BYTE_COUNT", byte_count)
// allocating a typed array
let arr = JSObjectMakeTypedArray(jsContext.jsGlobalContextRef!, kJSTypedArrayTypeUint8Array, byte_count, nil)
// just testing here to see how I'd write to this buffer (Note: is this the fastest way, or is all this memory binding slow?:
// getting the raw bytes
let ptr = JSObjectGetTypedArrayBytesPtr(jsContext.jsGlobalContextRef!, arr, nil)
//let buf = JSObjectGetTypedArrayBuffer(jsContext.jsGlobalContextRef, arr, nil)
let u8Ptr = ptr!.bindMemory(to: UInt8.self, capacity: byte_count)
//u8Ptr[0] = 5
return arr!
}
}
...
jsContext["mem"] = JSMemory.self
// js
const buf = new Uint8Array(mem.alloc(8)) // JS Exception: TypeError: mem.alloc is not a function. (In 'mem.alloc(8)', 'mem.alloc' is undefined)
I've seen variants of function binding that uses some sort of #convention attribute. Am I meant to use that instead?
What is the correct thing to do?
The documentation isn't very helpful unless you piece together a lot of information from separate sources. The seemingly working solution involves using parts of the older C API that are callable in Swift, unsafe pointers, and making sure the return values of the bound functions are JSValue?s. That makes sense since JavaScript functions all return an object, null, or undefined. An optional type mirrors this behavior.
Here is my work-in-progress code for anyone who might need some leads:
Just for an update, I've figured out how to mix the old C API with the new more limited Swift-specific APIs. I haven't yet made sure I'm not leaking memory, but it looks like I've found what I needed, hopefully.
In case you ever wanted to know:
#objc protocol JSMemoryExports: JSExport {
// note that I'm returning an optional
static func Uint8ArrayMake(_ count : JSValue) -> JSValue?
}
class JSMemory: NSObject, JSMemoryExports {
class func UInt8ArrayMake(_ count : JSValue) -> JSValue? {
guard !count.isUndefined && !count.isNull else {
return nil
}
let ref : JSValueRef = JSObjectMakeTypedArray(
JS_Controller.js.ctx.jsGlobalContextRef!,
kJSTypedArrayTypeUint8Array,
Int(count.toInt32()),
nil
)!
// if you want to modify the data
// let ptr = JSObjectGetTypedArrayBytesPtr(
// JS_Controller.js.ctx.jsGlobalContextRef!, ref, nil
// )
return JSValue(jsValueRef: ref, in: JS_Controller.js.ctx)
}
}
Here are a couple helpful references:
pointers in Swift
manual memory management in Swift

How to get all class initializers using reflection in Swift

I'm trying to get all signature of initializer from the class in Swift. Initializer can mirror, I can find the signatures like below code.
enum MessageType {
case say
case shout
case wisper
}
class Message {
var text = ""
var type : MessageType = .say
init(text: String, type: MessageType) {
self.type = type
self.text = text
}
init(text: String) {
self.text = text
}
}
let firstInit = Message.init(text:)
let secondInit = Message.init(text:type:)
let firstMirror = Mirror(reflecting: firstInit)
let secondMirror = Mirror(reflecting: secondInit)
print(firstMirror.subjectType)
// (String) -> Message
print(secondMirror.subjectType)
// ((String, MessageType)) -> Message
However, this code requires to specify init which I want to look it up. What I expected is something like below:
let mirror = Mirror(reflecting: Message)
let inits = mirror.initializers
// something like [Message.init(text:), Message.init(text:type:)] as [Any]
for method in inits {
let mirror = Mirror(reflecting: method)
print(method.subjectType)
}
How can I get all init initializers from class using Mirror?
The Mirror struct in Swift offers some runtime introspection features, but for the default case, these focus on the instance being reflected upon rather than the type of that instance. From the language reference for Mirror:
Mirror
Representation of the sub-structure and optional “display style” of any arbitrary subject instance.
Overview
Describes the parts—such as stored properties, collection elements, tuple elements, or the active enumeration case—that make up
a particular instance. May also supply a “display style” property that
suggests how this structure might be rendered.
You can implement a custom mirror for you Message type by conforming to the CustomReflectable protocol. Implementing a custom mirror with the single purpose of listing available initializers, however, would still require manually supplying the initializer's information to the implementation of the custom mirror.
E.g.:
extension Message: CustomReflectable {
var customMirror: Mirror {
let children = DictionaryLiteral<String, Any>(dictionaryLiteral:
("init(text:)", type(of: Message.init(text:))),
("init(text:type:)", type(of: Message.init(text:type:))))
return Mirror.init(Message.self, children: children,
displayStyle: .class)
}
}
// using your custom mirror
let myMessage = Message(text: "foo")
for case (let label?, let value) in Mirror(reflecting: myMessage).children {
print("\(label), \(value)")
} /* init(text:), (String) -> Message
init(text:type:), ((String, MessageType)) -> Message */
This manual implementation requirement possibly defeats the very purpose of the exercise though. Note also that reflection must still be performed upon an instance rather than the type itself (so possibly it's easier to simply implement a dictionary describing the initializers directly as a static type property; but the manual form of this implementation defeats much of its value).

Wait for one property to initialize and use it as reference for pulling data from db into another property, best practice?

I have a class, it has two properties:
var fruitsPackId: Int
var fruitsPackContent: Array<Fruit>?
Once the class is being initialized, I want to append data into fruintsPackContent from a local db according the the initialized fruitsPackId. I am not sure what is the best practice on that type of case.
What I did for now, is creating fruitsPackContent as a computed property, that pulls out the data from the local db using the fruitsPackId as reference id.
However, I feel that this is just not the right way of doing it, any ideas?
My code:
class FruitsPack: NSObject {
var fruitsPackId: Int
init(fruitsPackId: Int) {
self.fruitsPackId = fruitsPackId
}
var fruitsPackContent: Array<Fruit>? {
// Pulling data from local db here...
// For this example I create a dummy array with one instance of Fruit
let fruit1 = Fruit(fruitsPackId: self.fruitsPackId, fruitName: "Banana")
var fruits = Array<Fruit>()
fruits.append(fruit1)
return fruits
}
}
class Fruit: FruitsPack {
var fruitName: String
init(fruitsPackId: Int, fruitName: String) {
self.fruitName = fruitName
super.init(fruitsPackId: fruitsPackId)
}
}
EDIT:
Using lazy variable type did the work for me:
Class initialization has nothing to do with that property
Memory is being utilized only once property is being called
The property is being filled up with data only once
An instance method is available to be used by others
New code:
class FruitsPack: NSObject {
var fruitsPackId: Int
lazy var fruitsPackContent: Array<Fruit>? = self.getFruitsPackContent(self.fruitsPackId)
init(fruitsPackId: Int) {
self.fruitsPackId = fruitsPackId
}
func getFruitsPackContent(fruitsPackId: Int) -> Array<Fruit>? {
// Pulling data from local db here...
// For this example I create a dummy array with one instance of Fruit
let fruit1 = Fruit(fruitsPackId: self.fruitsPackId, fruitName: "Banana")
var fruits = Array<Fruit>()
fruits.append(fruit1)
return fruits
}
}
class Fruit: FruitsPack {
var fruitName: String
init(fruitsPackId: Int, fruitName: String) {
self.fruitName = fruitName
super.init(fruitsPackId: fruitsPackId)
}
}
Retrieving data from a database is a relatively computationally expensive process, so I'm not personally a fan of building that into a computed property. What if you innocently had some code that did the following:
for index in 0 ..< fruitPack.fruitsPackContent.count {
print(fruitPack.fruitsPackContent[index])
}
If you had n items in the database, this code might be repeatedly retrieving the full list of all items from the database n + 1 times (once for count and again for each subscripted access). You could, theoretically, remedy this by making sure that the computed property cached the results (and you'd have to build some code that would identify when the database was updated and invalidate the cache).
It would be more prudent to make the retrieval from the database an explicit method so that the app developer knows when they're retrieving data from the database, and when they're accessing a cached array. You generally want to avoid some significant hidden performance impact resulting from innocently accessing some property.

deep copy for array of objects in swift

I have this class named Meal
class Meal {
var name : String = ""
var cnt : Int = 0
var price : String = ""
var img : String = ""
var id : String = ""
init(name:String , cnt : Int, price : String, img : String, id : String) {
self.name = name
self.cnt = cnt
self.price = price
self.img = img
self.id = id
}
}
and I have an array of Meal :
var ordered = [Meal]()
I want to duplicate that array and then do some changes to the Meal instances in one of them without changing the Meal instances in the second one, how would I make a deep copy of it?
This search result didn't help me
How do I make a exact duplicate copy of an array?
Since ordered is a swift array, the statement
var orderedCopy = ordered
will effectively make a copy of the original array.
However, since Meal is a class, the new array will contain references
to the same meals referred in the original one.
If you want to copy the meals content too, so that changing a meal in one array will not change a meal in the other array, then you must define Meal as a struct, not as a class:
struct Meal {
...
From the Apple book:
Use struct to create a structure. Structures support many of the same behaviors as classes, including methods and initializers. One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
To improve on #Kametrixom answer check this:
For normal objects what can be done is to implement a protocol that supports copying, and make the object class implements this protocol like this:
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
And then the Array extension for cloning:
extension Array where Element: Copying {
func clone() -> Array {
var copiedArray = Array<Element>()
for element in self {
copiedArray.append(element.copy())
}
return copiedArray
}
}
and that is pretty much it, to view code and a sample check this gist
You either have to, as #MarioZannone mentioned, make it a struct, because structs get copied automatically, or you may not want a struct and need a class. For this you have to define how to copy your class. There is the NSCopying protocol which unifies that on the ObjC world, but that makes your Swift code "unpure" in that you have to inherit from NSObject. I suggest however to define your own copying protocol like this:
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
which you can implement like this:
class Test : Copying {
var x : Int
init() {
x = 0
}
// required initializer for the Copying protocol
required init(original: Test) {
x = original.x
}
}
Within the initializer you have to copy all the state from the passed original Test on to self. Now that you implemented the protocol correctly, you can do something like this:
let original = Test()
let stillOriginal = original
let copyOriginal = original.copy()
original.x = 10
original.x // 10
stillOriginal.x // 10
copyOriginal.x // 0
This is basically the same as NSCopying just without ObjC
EDIT: Sadly this yet so beautiful protocol works very poorly with subclassing...
A simple and quick way is to map the original array into the new copy:
let copyOfPersons: [Person] = allPersons.map({(originalPerson) -> Person in
let newPerson = Person(name: originalPerson.name, age: originalPerson.age)
return newPerson
})
The new Persons will have different pointers but same values.
Based on previous answer here
If you have nested objects, i.e. subclasses to a class then what you want is True Deep Copy.
//Example
var dogsForAdoption: Array<Dog>
class Dog{
var breed: String
var owner: Person
}
So this means implementing NSCopying in every class(Dog, Person etc).
Would you do that for say 20 of your classes? what about 30..50..100? You get it right? We need native "it just works!" way. But nope we don't have one. Yet.
As of now, Feb 2021, there is no proper solution of this issue. We have many workarounds though.
Here is the one I have been using, and one with less limitations in my opinion.
Make your class conforms to codable
class Dog: Codable{
var breed : String = "JustAnyDog"
var owner: Person
}
Create this helper class
class DeepCopier {
//Used to expose generic
static func Copy<T:Codable>(of object:T) -> T?{
do{
let json = try JSONEncoder().encode(object)
return try JSONDecoder().decode(T.self, from: json)
}
catch let error{
print(error)
return nil
}
}
}
Call this method whenever you need true deep copy of your object, like this:
//Now suppose
let dog = Dog()
guard let clonedDog = DeepCopier.Copy(of: dog) else{
print("Could not detach Dog")
return
}
//Change/mutate object properties as you want
clonedDog.breed = "rottweiler"
//Also clonedDog.owner != dog.owner, as both the owner : Person have dfferent memory allocations
As you can see we are piggy backing on Swift's JSONEncoder and JSONDecoder, using power of Codable, making true deep copy no matter how many nested objects are there under our object. Just make sure all your Classes conform to Codable.
Though its NOT an ideal solution, but its one of the most effective workaround.

NSUserDefaults in Swift - implementing type safety

One of the things that bugs me about Swift and Cocoa together is working with NSUserDefaults, because there is no type information and it is always necessary to cast the result of objectForKey to what you are expecting to get. It is unsafe and impractical. I decided to tackle this problem, making NSUserDefaults more practical in Swift-land, and hopefully learning something along the way. Here were my goals in the beginning:
Complete type safety: each key has one type associated with it. When setting a value, only a value of that type should be accepted and when getting a value the result should come out with the correct type
Global list of keys which are clear in meaning and content. The list should be easy to create, modify and extend
Clean syntax, using subscripts if possible. For example, this would
be perfect:
3.1. set: UserDefaults[.MyKey] = value
3.2. get: let value = UserDefaults[.MyKey]
Support for classes that conform to the NSCoding protocol by
automatically [un]archiving them
Support for all property list types accepted by NSUserDefaults
I started by creating this generic struct:
struct UDKey <T> {
init(_ n: String) { name = n }
let name: String
}
Then I created this other struct that serves as a container for all the keys in an application:
struct UDKeys {}
This can then be extended to add keys wherever needed:
extension UDKeys {
static let MyKey1 = UDKey<Int>("MyKey1")
static let MyKey2 = UDKey<[String]>("MyKey2")
}
Note how each key has a type associated with it. It represents the type of the information to be saved. Also, the name property is the string that is to be used as a key for NSUserDefaults.
The keys can be listed all in one constants file, or added using extensions on a per-file basis close to where they are being used for storing data.
Then I created an "UserDefaults" class responsible for handling the getting/setting of information:
class UserDefaultsClass {
let storage = NSUserDefaults.standardUserDefaults()
init(storage: NSUserDefaults) { self.storage = storage }
init() {}
// ...
}
let UserDefaults = UserDefaultsClass() // or UserDefaultsClass(storage: ...) for further customisation
The idea is that one instance for a particular domain is created and then every method is accessed in this way:
let value = UserDefaults.myMethod(...)
I prefer this approach to things like UserDefaults.sharedInstance.myMethod(...) (too long!) or using class methods for everything. Also, this allows interacting with various domains at the same time by using more than one UserDefaultsClass with different storage values.
So far, items 1 and 2 have been taken care of, but now the difficult part is starting: how to actually design the methods on UserDefaultsClass in order to comply with the rest.
For example, let's start with item 4. First I tried this (this code is inside UserDefaultsClass):
subscript<T: NSCoding>(key: UDKey<T>) -> T? {
set { storage.setObject(NSKeyedArchiver.archivedDataWithRootObject(newValue), forKey: key.name) }
get {
if let data = storage.objectForKey(key.name) as? NSData {
return NSKeyedUnarchiver.unarchiveObjectWithData(data) as? T
} else { return nil }
}
}
But then I find out that Swift doesn't allow generic subscripts!! Alright, then I guess I'll have to use functions then. There goes half of item 3...
func set <T: NSCoding>(key: UDKey<T>, _ value: T) {
storage.setObject(NSKeyedArchiver.archivedDataWithRootObject(value), forKey: key.name)
}
func get <T: NSCoding>(key: UDKey<T>) -> T? {
if let data = storage.objectForKey(key.name) as? NSData {
return NSKeyedUnarchiver.unarchiveObjectWithData(data) as? T
} else { return nil }
}
And that works just fine:
extension UDKeys { static let MyKey = UDKey<NSNotification>("MyKey") }
UserDefaults.set(UDKeys.MyKey, NSNotification(name: "Hello!", object: nil))
let n = UserDefaults.get(UDKeys.MyKey)
Note how I can't call UserDefaults.get(.MyKey). I have to use UDKeys.MyKey. And I can't do that because it's not yet possible to have static variables on a generic struct!!
Next, let's try number 5. Now that has been an headache and that's where I need lots of help.
Property list types are, as per the docs:
A default object must be a property list, that is, an instance of (or
for collections a combination of instances of): NSData, NSString,
NSNumber, NSDate, NSArray, or NSDictionary.
That in Swift means Int, [Int], [[String:Bool]], [[String:[Double]]], etc are all property list types. At first I thought that I could just write this and trust whoever is using this code to remember that only plist types are allowed:
func set <T: AnyObject>(key: UDKey<T>, _ value: T) {
storage.setObject(value, forKey: key.name)
}
func get <T: AnyObject>(key: UDKey<T>) -> T? {
return storage.objectForKey(key.name) as? T
}
But as you'll notice, while this works fine:
extension UDKeys { static let MyKey = UDKey<NSData>("MyKey") }
UserDefaults.set(UDKeys.MyKey, NSData())
let d = UserDefaults.get(UDKeys.MyKey)
This doesn't:
extension UDKeys { static let MyKey = UDKey<[NSData]>("MyKey") }
UserDefaults.set(UDKeys.MyKey, [NSData()])
And this doesn't either:
extension UDKeys { static let MyKey = UDKey<[Int]>("MyKey") }
UserDefaults.set(UDKeys.MyKey, [0])
Not even this:
extension UDKeys { static let MyKey = UDKey<Int>("MyKey") }
UserDefaults.set(UDKeys.MyKey, 1)
The problem is that they are all valid property list types yet Swift obviously interprets arrays and ints as structs, not as their Objective-C class counterparts. However:
func set <T: Any>(key: UDKey<T>, _ value: T)
won't work either, because then any value type, not just the ones that have a class cousin courtesy of Obj-C, is accepted, and storage.setObject(value, forKey: key.name) is no longer valid because value has to be a reference type.
If a protocol existed in Swift that accepted any reference type and any value type that can be converted to a reference type in objective-c (like [Int] and the other examples I mention) this problem would be solved:
func set <T: AnyObjectiveCObject>(key: UDKey<T>, _ value: T) {
storage.setObject(value, forKey: key.name)
}
func get <T: AnyObjectiveCObject>(key: UDKey<T>) -> T? {
return storage.objectForKey(key.name) as? T
}
AnyObjectiveCObject would accept any swift classes and swift arrays, dictionaries, numbers (ints, floats, bools, etc that convert to NSNumber), strings...
Unfortunately, AFAIK this doesn't exist.
Question:
How can I have write a generic function (or collection of overloaded generic functions) whose generic type T can be any reference type or any value type that Swift can convert to a reference type in Objective-C?
Solved: With the help of the answers I got, I arrived at what I wanted. In case anyone wants to take a look at my solution, here it is.
I don't mean to brag but ... oh who am I kidding, I totally do!
Preferences.set([NSData()], forKey: "MyKey1")
Preferences.get("MyKey1", type: type([NSData]))
Preferences.get("MyKey1") as [NSData]?
func crunch1(value: [NSData])
{
println("Om nom 1!")
}
crunch1(Preferences.get("MyKey1")!)
Preferences.set(NSArray(object: NSData()), forKey: "MyKey2")
Preferences.get("MyKey2", type: type(NSArray))
Preferences.get("MyKey2") as NSArray?
func crunch2(value: NSArray)
{
println("Om nom 2!")
}
crunch2(Preferences.get("MyKey2")!)
Preferences.set([[String:[Int]]](), forKey: "MyKey3")
Preferences.get("MyKey3", type: type([[String:[Int]]]))
Preferences.get("MyKey3") as [[String:[Int]]]?
func crunch3(value: [[String:[Int]]])
{
println("Om nom 3!")
}
crunch3(Preferences.get("MyKey3")!)
I'd like to introduce my idea. (Sorry for my poor English in advance.)
let plainKey = UDKey("Message", string)
let mixedKey
= UDKey("Mixed"
, array(dictionary(
string, tuple(
array(integer),
optional(date)))))
let ud = UserDefaults(NSUserDefaults.standardUserDefaults())
ud.set(plainKey, "Hello")
ud.set(plainKey, 2525) // <-- compile error
ud.set(mixedKey, [ [ "(^_^;)": ([1, 2, 3], .Some(NSDate()))] ])
ud.set(mixedKey, [ [ "(^_^;)": ([1, 2, 3], .Some(NSData()))] ]) // <-- compile error
The only difference is that UDKey() now requires #2 argument, a value of BiMap class. I've uncoupled the work originally of UDKey into BiMap which converts a value of a type to/from a value of another type.
public class BiMap<A, B> {
public func AtoB(a: A) -> B?
public func BtoA(b: B) -> A?
}
Consequently, types that set/get can accepts are conducted by BiMap, and no longer limited to types as can automatically cast
from/to AnyObject (more specifically, types NSUserDefaults can accepts.).
Because BiMap is a generic class, you can easily create subtypes of that, interchanging arbitrary two types you want.
Here is full source code. (But there are bugs yet to be fixed..)
https://gist.github.com/hisui/47f170a9e193168dc946