Skip to content

Instantly share code, notes, and snippets.

@tjhancocks
Created October 2, 2015 10:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjhancocks/a488047de4752fa0b6a0 to your computer and use it in GitHub Desktop.
Save tjhancocks/a488047de4752fa0b6a0 to your computer and use it in GitHub Desktop.
class Object {
func doSomething() {
print("Hello, World")
}
}
class Sum {
var a: Int = 0
var b: Int = 0
var c: Int = 8
func display() {
print("\(a) + \(b) = \(a+b)")
}
}
ObjectMapper.sharedInstance.map(klass: Object.self, withName: "Object")
ObjectMapper.sharedInstance.map(klass: Sum.self, withName: "Sum")
// Basic setup
if let obj = GetObjectFactory(classNamed: "Object").buildObject() as? Object {
obj.doSomething()
}
// Actually setting values before building the object
print("------ First Test -----")
let sumFactory = GetObjectFactory(classNamed: "Sum")
sumFactory.set(variableName: "a", value: 2)
sumFactory.set(variableName: "b", value: 7)
sumFactory.set(variableName: "c", value: 8888)
var firstSum = Sum()
if let sum = sumFactory.buildObject() as? Sum {
sum.display()
firstSum = sum
print("first")
}
// reuse sumFactory
print("------ Second Sum Test -----")
sumFactory.prepareNextInstance()
sumFactory.set(variableName: "a", value: 56)
sumFactory.set(variableName: "b", value: 3)
sumFactory.set(variableName: "c", value: 1111)
var secondSum = Sum()
if let sum = sumFactory.buildObject() as? Sum {
sum.display()
secondSum = sum
}
// display both of them... this should hopefully work
print("------ Final Sum Test -----")
firstSum.display()
secondSum.display()
import ObjectiveC
class ObjectFactory {
let internalClass: AnyClass
var rawMemory: UnsafeMutablePointer<Void>?
init(usingClass klass: AnyClass) {
self.internalClass = klass
constructInstance()
}
private func calculateInstanceSize() -> Int {
return class_getInstanceSize(internalClass)
}
private func constructInstance() {
if let _ = rawMemory { fatalError("Attempted to construct an instance whilst already constructing an instance") }
// setup memory for a new instance of the object
let size = calculateInstanceSize()
rawMemory = UnsafeMutablePointer<Void>.alloc(size)
guard let rawMemory = rawMemory else { fatalError() }
memset(rawMemory, 0, size)
// make sure the instance has the correct class
let classFieldMemory = UnsafeMutablePointer<AnyClass>(rawMemory)
classFieldMemory[0] = internalClass
}
func buildObject() -> AnyObject {
guard let rawMemory = rawMemory else { fatalError() }
let object = ConvertPointerToObject(rawMemory)
self.rawMemory = nil
return object
}
func prepareNextInstance() {
constructInstance()
}
/// KVC Style Setters
func set(variableName name: String, value: Int) -> ObjectFactory {
guard let rawMemory = rawMemory else { fatalError() }
VariableSetter<Int>.set(name, value: value, inClass: internalClass, againstMemory: rawMemory)
return self
}
func set(variableName name: String, value: Float) -> ObjectFactory {
guard let rawMemory = rawMemory else { fatalError() }
VariableSetter<Float>.set(name, value: value, inClass: internalClass, againstMemory: rawMemory)
return self
}
func set(variableName name: String, value: Double) -> ObjectFactory {
guard let rawMemory = rawMemory else { fatalError() }
VariableSetter<Double>.set(name, value: value, inClass: internalClass, againstMemory: rawMemory)
return self
}
}
private class VariableSetter<T> {
class func set(name: String, value: T, inClass kls: AnyClass, againstMemory memory: UnsafeMutablePointer<Void>) {
let ivar = class_getInstanceVariable(kls, name)
let variableFields = UnsafeMutablePointer<T>(memory)
variableFields[ivar_getOffset(ivar) / strideof(T)] = value
}
}
import ObjectiveC
class ObjectMapper {
static let sharedInstance = ObjectMapper()
private var map = [String: AnyClass]()
func map(klass klass: AnyClass, withName name: String? = nil) {
if let name = name {
map[name] = klass
}
else if let name = String.fromCString(class_getName(klass)) {
map[name] = klass
}
else {
fatalError()
}
}
func klass(forName name: String) -> AnyClass {
guard let klass = map[name] else { fatalError() }
return klass
}
func factory(forClassNamed name: String) -> ObjectFactory {
guard let klass = map[name] else { fatalError() }
return ObjectFactory(usingClass: klass)
}
}
func GetObjectFactory(classNamed name: String) -> ObjectFactory {
return ObjectMapper.sharedInstance.factory(forClassNamed: name)
}
Hello, World
------ First Test -----
2 + 7 = 9
------ Second Sum Test -----
56 + 3 = 59
------ Final Sum Test -----
2 + 7 = 9
56 + 3 = 59
Program ended with exit code: 0
#ifndef SwiftHelper_h
#define SwiftHelper_h
_Nonnull id ConvertPointerToObject(const void * _Nonnull ptr);
#endif /* SwiftHelper_h */
#include "SwiftHelper.h"
_Nonnull id ConvertPointerToObject(const void * _Nonnull ptr)
{
return (__bridge id)ptr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment