2016-04-03 13 views
1

これは私のプログラミング理解の範囲外です。この概念を理解する助けがあれば、非常に感謝しています。オブジェクト変数を別の変数へのポインタにする

私が持っているものは、レイヤークラスFloaterContainerLayerです。

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

私は、このクラスの3つのインスタンスを常に持っています。それらの1つは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") 
    } 
} 

ここで、この値はいつでも変更できます。私はdotLayer.gravityを1秒間に60回呼び出すビューレンダリング方法で使用します。私は dotLayer.gravity = dotLayerGravity

を設定し、 dotLayer.gravityを呼び出す

が、私はそれがdotLayerGravityを返すようにしたい:私は達成したい何

は、ということです。

クラス内の重力変数をdotLayerGravityに設定することは、クラスが3つのインスタンスに対して使用されるため、オプションではありません。

私はこれを試しましたが、動作しません。 enter image description here

答えて

3

必要があることを意味します。考えられる解決策の1つは、ポインタとして機能する単純なラッパークラスを作成することです。

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 
     } 
    } 
} 

valueは、それはあなたのアプリケーションでどこでもアクセスできるようになりますstaticプロパティですので。これはすべて必要というわけではありませんが、この値のインスタンスが1つしか存在しないことを保証します。

inMemoryprivateであり、書き込み操作が完了するまで値はNSUserDefaultsから保持されます。クラスにクリーナーインターフェースを与えるのはprivateです。

あなたがvalueの値を取得する場合、それはinMemoryをアンラップすることにより、メモリ内の値を有する場合には、まずチェックします、それはnilであれば、それはNSUserDefaultsにフォールバックされます、それはまたnilあるとき、それはデフォルト値にフォールバックします。

フェッチされた値またはデフォルト値をinMemoryに保存し、最終結果を返します。 NSUserDefaultsからの読み取りを最小限に抑えます。

これはスレッドセーフではありませんが、作成することができます。

あなたの質問を読み直す

は、各インスタンスは、それがNSUserDefaultsに保存されている自身のgravityのしているように私にはそれが明らかにしました。その場合は、を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の部分を恐れていることを認識していましたが、それが後で問題になると思いました。私が読んだところでは、問題を扱うかなりOKのキャッシュを維持していますが、必要ならば私はあなたのソリューションを使用します。 CGFloatsに関してポイントできない点については、これについては確かですか?私はここでそれを使っている他の人を見つけました。 –

+0

@OscarApeland私は彼らがポイント可能ではないとは言っていませんでした(それが何であるかは分かりません)。彼らは参照型ではないので、ポインタの振る舞いは自分ではありません。 –

+0

ああ。私はあなたを誤解していた、私はお詫び申し上げます。 NSUserDefaultsの部分についても、フレーム0から100%のCPU使用率が正しいことが分かります。 –

1

参照ポインタの設定は、関数ではなくプロパティでのみサポートされます。これは、彼らが値型であるため、ポインタがスウィフトは不可能であるとして、あなたは... CGFloat /フロート/ダブル/ INTを使用して設定する方法を

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 
関連する問題