スポンサーサイト

--/--/--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
comment (-) @ スポンサー広告

[Swift] シーン変更によるクラスの持続と破棄・インスタンスの持続と破棄

2015/07/23
まず、クラスの概念について、私はまだ完全に理解していません。
というか、ほとんど分かっていません。

というかクラスをどんな風に利用するのが適切なのかが、
分かっていないんだと思います。

しかし、それでも手探りに利用しているわけですが、
そのせいで、様々な不具合のような現象に出くわします。

1、SpriteKitのSKシーン切り替え時に、クラスやインスタンスはどのように残ったり、自動破棄されたりするのか。

現在のSwiftでは、クラスは参照元がなくなると自動破棄されるようです。
そのため、SKシーンを切り替えたりすれば、SKシーンのインスタンスが破棄されるため、
それによってクラスは自動消滅し、データ等を自分で破棄したりする必要がないとのことらしいのですが、
しかし、実際にはものすごくクラスが残っていたりするかもしれません。

たとえばSpriteKitにあるSKNodeですが、
シーン表示させているクラス内で作成したNodeを、
異なる二つの別クラスに、それぞれのインスタンス時に受け渡したケースで、

このNodeは、シーン切り替え3回目あたりで、突然表示されなくなるという
怪奇現象に出くわしました。

私がクラスを理解していないので、完全にあてずっぽうですが、
多分、二つ以上の別クラスに、メインクラスのnode等を受け渡した場合、
メインクラスのシーンを切り替えても、
その二つの別クラスのインスタンスは破棄されずに残っているんだと予想します。

この二つの別クラスは、メインクラスからインスタンス化しているので、
メインクラスが破棄されれば、自動的に参照元を失うはずなのですが、なぜか残り続けます。

こういうのは、多分そうじゃないかなーと警戒していても、
扱うクラスやインスタンスやnodeが膨大になればなるほど、
絶対に知らないうちに発生することだと思うのですが・・・。

なので、偶然発見できればいいのですが、もし発見できなかった場合は、
致命的なクラッシュバグ等として残ることになる非常に危険なものだと思います。


2、クラス内タイマーは残る。

NSTimer というタイマーがありますが、
これをクラス内で使用すると、個別に稼働するタイマーとなり非常に便利になります。
しかしこのタイマー、SKシーンが切り替わろうが、インスタンス元を破棄しようが、ずっと動き続けているようです。

なのでクラス内でタイマーを走らせる場合、
シーン切り替え時などには、
インスタンスしたクラス全てに対し、タイマーを止めるメソッドを実行してやらねばなりません。


・・・とまあ、今の所気づいただけでこのような重大な要素があるので、
きっとまだまだありそうです。

そして、これらのインスタンスがずっと残り続けると、
SKシーンの切り替えを行うたびに、それらが不要に重複し、思わぬ不具合を引き起こす原因となりそうです。


■ 対策 ■

SKシーン切り替え時には、SKシーンや各クラスに、

Dinit{
   println (" class名 end!! ")
}

の一文を挿入する。

これで、一応そのクラスのインスタンスが完全に破棄されたかどうかが判明します。

破棄されていないとしたら、私の場合の多くは、

・そのクラス内で使用しているNSTimerが破棄できていない。
  or
・そのクラス内で宣言したSKNodeを、2つ以上の別クラスに参照させている。

の2つが多いです。
前者は、シーン切り替え前に、NSTimerを終了させればOKですが、
後者は見落とす可能性が高いです。
対策としては、なるべくSKNodeを参照させる場合、個別にSKNodeを作って参照させ、
共有を避けるということくらいでしょうか。


最後に、
これらを一切考慮せずに済む方法は、
私の思いつく限りだと、SKシーンの切り替えはせずに、
表示させるシーンは常に1つに固定するという手法でしょうか。

そして画面遷移は、自分で全ての描画を管理することで、
シーン切り替えを利用せずに、自前で行えば、
シーンのクラスを呼び出すのは一度だけとなり、
再インスタンス化するというケースを排除できます。
そうなれば、クラスやインスタンスの不要な持続や破棄をいちいち考えずに済むではと予想します。


クラスを使用すると、
様々なものを個別に管理でき、
また再利用もできるのでとても便利です。

でも、予期しないことがあまりに多すぎて、
そういう対処に、大半の時間を持って行かれている感じです。

こんなことなら、
クラスは最低限の使用にとどめ、
その他全てを自分で構築した一つのループの中で回す方が、
何倍も開発速度が上がりそうです。

インスタンスが破棄されずに残っていることが一目でわかるようなシステムや、
そういうケースが発生した場合には警告で教えてくれたりすれば、まだいいのですが、
そんなことも一切ないし・・。

とまあ、時代に逆行したようなことを言ってみましたが、
個人で全てをやっているので、他人との共有管理を予定する必要がないし、
また一方、予期しない問題が発生すると個人では対応できない可能性が高いという点からも、
ひとりでゲーム開発なんかをやっている人には、
この辺、本当にめんどうな問題だと思います。


UIKitをSpriteKitと一緒に導入した時に、あまりにUIKitの仕様に手こずった時にも思いましたが、
UIにしても、こういう便利だと提示されがちなプログラム要素にしても、
私の場合は、0から自分で作った方が、結局早いし便利だったりするのが、
なんだか個人的に時代とマッチしていない感じがして、いつもちょっと寂しいです。
関連記事
comment (0) @ エラー
[Swift] SpriteKit SKSceneからpresentViewControllerを使う方法 | [ダウンロード数] スマホゲームレビューサイトに載った翌日。

comment

コメントを送る。

URL:
Comment:
Pass:
Secret: 管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。