2016-04-03 98 views
1

这是远远不能达到我的编程理解,所以任何帮助理解这个概念将非常赞赏。使对象变量指向另一个变量

我所拥有的是一个图层类FloaterContainerLayer。

class FloaterContainerLayer:CALayer { 
    var gravity:CGFloat = 5.0 
    var maxFloaters = 9 
    var image:String? 
    var velocity:CGFloat = 50.0 
} 

我在任何时候都有这个类的三个实例。其中之一是dotLayer。

lazy var dotLayer : FloaterContainerLayer = { 
     let scrollLayer = FloaterContainerLayer() 
     scrollLayer.bounds = self.view.layer.bounds 
     scrollLayer.position = CGPoint(x: self.view.bounds.size.width/2, y: self.view.bounds.size.height/2) 
     scrollLayer.image = "dot" 
     scrollLayer.gravity = dotLayerGravity 

     return scrollLayer 
    }() 

别的地方,我有一个重力变量的点层。

var dotLayerGravity: CGFloat { 
    get { 
     if let stored = userDefaults.objectForKey("dotLayerGravity") { 
      return CGFloat(stored as! NSNumber) 
     } 
     else { 
      return 10.0 
     } 
    } 
    set(value) { 
     userDefaults.setValue(value, forKey: "dotLayerGravity") 
    } 
} 

现在,这个值可以在任何时候改变。我在每秒调用60次的视图渲染方法中使用dotLayer.gravity

我想完成的是:

当我设置 dotLayer.gravity = dotLayerGravity

,并呼吁 dotLayer.gravity

我想它返回dotLayerGravity

仅将类中的重力变量设置为dotLayerGravity不是一个选项,因为该类用于三个实例。

我试过这个,但它不起作用。 enter image description here

回答

3

使用CGFloat的/浮点/双精度/诠释,......作为指针是不可能的斯威夫特,因为他们是值类型。一种可能的解决方案是创建一个简单的包装类,作为指针。

class CGFloatPointer : FloatLiteralConvertible { 

    var value : CGFloat = 0 

    required convenience init(floatLiteral value: Float) { 
     self.init() 
     self.value = CGFloat(value) 
    } 
} 

你可以用FloatLiteralConvertible这样的东西来扩展这个类,使它更易于使用。

var gravity:CGFloatPointer = 5.0 

这比UnsafePointer要容易得多。


一个小小的细节。听起来你的解释是你将会很多地从/向UserDefaults加载/保存。这很糟糕,因为它很慢。

对于你的一段代码,我会推荐一些全局变量和单例之间的一半,并引入一些额外的魔法来管理读/写操作。

class DotLayerGravity { 
    private static var inMemory : CGFloat? 
    static var value: CGFloat { 
     get { 
      if let inMemory = inMemory { 
       return inMemory 
      } else { 
       let fetchedGravity = (NSUserDefaults.standardUserDefaults().objectForKey("dotLayerGravity") as? NSNumber) ?? 10 
       inMemory = CGFloat(fetchedGravity) 
       return inMemory! 
      } 
     } 
     set(value) { 
      NSUserDefaults.standardUserDefaults().setValue(value, forKey: "dotLayerGravity") 
      // setting this to nil will make it fetch from permanenent storage. 
      inMemory = nil 
     } 
    } 
} 

因为valuestatic财产将被访问无处不在你的应用程序。这完全不是必需的,但它确实保证只有这个值的一个实例。

inMemoryprivate并且将保持从NSUserDefaults的值,直到写操作完成为止。这是private给班级一个更清洁的界面。

当你的value值会首先检查是否有通过展开inMemory,如果是nil,它将退回上NSUserDefaults,当也nil在内存中的值,它将退回上一个默认值。

它将在inMemory中存储提取或默认值并返回最终结果。 这确保了从NSUserDefaults的最小读取。

这不是线程安全的,但可以做成。


重读你的问题,明确向我,每个实例有它的存储NSUserDefaults自己gravity。在这种情况下,我会通过设置FloaterContainerLayer全部负责gravity,并且identifierString将用于加载/保存到NSUserDefaults

class FloaterContainerLayer:CALayer { 

    var maxFloaters = 9 
    var image:String? 
    var velocity:CGFloat = 50.0 

    var identifier : String = "floaterContainerIdentifier" 

    private var inMemoryGravity : CGFloat? 
    var gravity: CGFloat { 
     get { 
      if let inMemory = inMemoryGravity { 
       return inMemory 
      } else { 
       let fetchedGravity = (NSUserDefaults.standardUserDefaults().objectForKey(identifier) as? NSNumber) ?? 10 
       inMemoryGravity = CGFloat(fetchedGravity) 
       return inMemoryGravity! 
      } 
     } 
     set(value) { 
      NSUserDefaults.standardUserDefaults().setValue(value, forKey: identifier) 
      // setting this to nil will make it fetch from permanenent storage. 
      inMemoryGravity = nil 
     } 
    } 
} 

class SomeViewController : UIViewController { 

    lazy var dotLayer : FloaterContainerLayer = { 
     let scrollLayer = FloaterContainerLayer() 
     scrollLayer.bounds = self.view.layer.bounds 
     scrollLayer.position = CGPoint(x: self.view.bounds.size.width/2, y: self.view.bounds.size.height/2) 
     scrollLayer.image = "dot" 
     scrollLayer.identifier = "dotLayerGravity" 

     return scrollLayer 
    }() 
} 
+0

这就是很多很好的输入。我知道并且害怕UserDefaults部分,如果这是一个问题,我认为我稍后会处理它。从我读过的内容来看,它保持着一个很好的缓存来处理这个问题,但如果必须的话,我会使用你的解决方案。 关于CGFloats不可指向性,你确定吗?我发现其他人在这里使用它。 –

+0

@OscarApeland我没有说他们不是可指向的(甚至不知道是什么),他们只是不是引用类型,所以他们没有自己的指针行为。 –

+0

哦。我误解了你,我很抱歉。原来你对NSUserDefaults部分也是正确的,从第0帧开始100%的CPU使用率。 –

1

设置引用指针只支持函数,而不支持属性。这意味着你需要一套方法

var testVariable: CGFloat = 100.0 

class Test { 
    var testPtr: UnsafePointer<CGFloat>? 

    func setTestPtr(ptr: UnsafePointer<CGFloat>) { 
     self.testPtr = ptr 
    } 
} 

let t = Test() 
t.setTestPtr(&testVariable) 

testVariable = 110 

let x = t.testPtr?.memory // 110