سؤال

أريد تخزينًا في حالات فئة معينة. يحتفظ الفصل بقاموس جميع الحالات ، وعندما يطلب شخص ما مثيلًا جديدًا ، يحاول الفصل تلبية الطلب من ذاكرة التخزين المؤقت أولاً. هناك مشكلة صغيرة في إدارة الذاكرة: يحتفظ ذاكرة التخزين المؤقت للقاموس بالكائنات المدرجة ، بحيث لا يتم توصيلها أبدًا. أريدهم أن يتعاملوا ، بحيث اضطررت إلى زيادة التحميل release الطريقة وعندما تنخفض عدد الاحتفاظ بآخر ، يمكنني إزالة المثيل من ذاكرة التخزين المؤقت والسماح له بالتعامل.

هذا يعمل ، لكنني لست مرتاحًا حول release الطريقة وابحث عن الحل معقدًا بشكل مفرط. اعتقدت أنه يمكنني استخدام بعض فئات التجزئة التي لا تحتفظ بالكائنات التي تخزنها. هل هناك هذا؟ الفكرة هي أنه عندما يطلقه آخر مستخدم لمثيل معين ، فإن المثيل سيختفي تلقائيًا من ذاكرة التخزين المؤقت.

nshashtable يبدو أن ما أبحث عنه ، لكن الوثائق تتحدث عن "دعم العلاقات الضعيفة في بيئة تم جمعها القمامة". هل تعمل أيضًا بدون جمع القمامة؟


توضيح: لا يمكنني تحمل تكاليف الحفاظ على الحالات في الذاكرة ما لم يكن شخص ما يحتاج إليها حقًا ، ولهذا السبب أريد تطهير المثيل من ذاكرة التخزين المؤقت عندما يطلقه المستخدم "الحقيقي" الأخير.


حل أفضل: كان هذا على iPhone ، أردت تخزين بعض القوام ، ومن ناحية أخرى ، أردت تحريرها من الذاكرة بمجرد أن أصدرها آخر حامل حقيقي. الطريقة الأسهل لترميز هذا من خلال فئة أخرى (دعنا نسميها TextureManager). تدير هذه الفئة مثيلات الملمس وتخزينها ، بحيث يتم تقديم المكالمات اللاحقة للملمس بنفس الاسم من ذاكرة التخزين المؤقت. ليست هناك حاجة لتطهير ذاكرة التخزين المؤقت فورًا حيث يقوم المستخدم الأخير بإطلاق الملمس. يمكننا ببساطة الحفاظ على الملمس المخبأة في الذاكرة ، وعندما يكون الجهاز قصيرًا على الذاكرة ، نتلقى تحذيرًا منخفضًا من الذاكرة ويمكننا تطهير ذاكرة التخزين المؤقت. هذا حل أفضل ، لأن أشياء التخزين المؤقت لا تلوث Texture الفصل ، ليس علينا أن نتعبث مع release وهناك حتى فرصة أعلى لضربات ذاكرة التخزين المؤقت. ال TextureManager يمكن استخلاصه في ResourceManager, ، بحيث يمكنه تخزين البيانات الأخرى ، وليس فقط القوام.

هل كانت مفيدة؟

المحلول

نعم ، يمكنك استخدام nshashtable لإنشاء ما هو في الأساس قاموس غير محافظ. بدلاً من ذلك ، يمكنك استدعاء cfdictionarycreate مع NULL للإصدار والاحتفاظ باستدعاءات. يمكنك بعد ذلك ببساطة كتابة النتيجة إلى nsdictionary بفضل سد Tollfree ، واستخدامها تمامًا مثل NSDictionary العادي باستثناء عدم التغلب على التهم الاحتفاظ بها.

إذا قمت بذلك ، فلن يقوم القاموس تلقائيًا بتصنيف المرجع ، فستحتاج إلى التأكد من إزالته عند تعامل مثيل.

نصائح أخرى

ما تريده هو مرجع ضعيف Zeroing (إنه ليس "خوارزميات إدارة ذاكرة التخزين المؤقت" ، إنه نمط معروف). تكمن المشكلة في أن الهدف C يوفر لك صفر مراجع ضعيفة فقط عند تشغيل جمع القمامة ، وليس في البرامج اليدوية المدارة للذاكرة. ولا يوفر iPhone جمع القمامة (حتى الآن).

يبدو أن جميع الإجابات حتى الآن توجهك إلى نصف حلول.

لا يكفي استخدام مرجع غير راسخ لأنك ستحتاج إلى صفر (أو إزالة الإدخال من القاموس) عند توزيع الكائن المشار إليه. ومع ذلك ، يجب أن يتم ذلك قبل أن يسمى طريقة -dealloc لهذا الكائن وإلا فإن وجود ذاكرة التخزين المؤقت يعرضك للخطر الذي يتم إحياء الكائن. تتمثل طريقة القيام بذلك في الفئة الفرعية ديناميكيًا عند إنشاء المرجع الضعيف ، وفي الفئة الفرعية التي تم إنشاؤها ديناميكيًا ، تجاوز -إعادة الإفراج لاستخدام قفل و -اللوك لزيادة المرجع (المرجع) الضعيف.

هذا يعمل بشكل عام لكنه يفشل فشلاً ذريعًا في كائنات الأساس الأساسية المجانية. لسوء الحظ ، فإن الحل الوحيد ، إذا كنت بحاجة إلى تمديد التقنية إلى الكائنات المجانية المجانية ، يتطلب بعض الأشياء غير الموثقة (انظر هنا بالنسبة للرمز والتفسيرات) ، وبالتالي لا يمكن استخدامها لنظام التشغيل iOS أو البرامج التي تريد بيعها على متجر تطبيقات Mac.

إذا كنت بحاجة إلى البيع على متاجر Apple ، وبالتالي يجب تجنب الأشياء غير الموثقة ، فإن أفضل بديل لك هو تنفيذ الوصول المقفل إلى ذاكرة التخزين المؤقت المحتفظ به ثم تفكيكه للمراجع ذات قيمة -Retaincount الحالية عند 1 عندما تريد تحرير الذاكرة. طالما أن جميع الوصول إلى ذاكرة التخزين المؤقت مع القفل المعمول به ، إذا لاحظت عددًا من 1 أثناء حمل القفل ، فأنت تعلم أنه لا يوجد أحد يمكنه إحياء الكائن إذا قمت بإزالته من ذاكرة التخزين المؤقت (وبالتالي تحريره ) قبل التخلي عن القفل.

بالنسبة لنظام التشغيل iOS ، يمكنك استخدام uiapplicationdidreceiveMemoryWarningNotification لتحريك الكسح. على جهاز Mac ، تحتاج إلى تنفيذ المنطق الخاص بك: ربما مجرد فحص دوري أو حتى مجرد تفكيك دوري (سيعمل كلا الحللين أيضًا على iOS).

لقد قمت للتو بتنفيذ هذا النوع من الأشياء باستخدام nsmutabletictionary والتسجيل في uiapplicationDidReceiveMemoryWarningNotification. على تحذير من الذاكرة أقوم بإزالة أي شيء من القاموس مع الاحتفاظ بـ 1 ...

استخدم [nsvalue valuewithnonteedobject:] لفت المثيل في nsvalue ووضع ذلك في القاموس. في طريقة Dealloc على سبيل المثال ، قم بإزالة الإدخال المقابل من القاموس. لا العبث مع الاحتفاظ.

ما أفهمه هو أنك تريد تنفيذ خوارزميات إدارة ذاكرة التخزين المؤقت: إسقاط العناصر التي لن يتم استخدامها بعد الآن.

قد ترغب في النظر في معايير أخرى ، مثل إسقاط العناصر الأقل طلبًا مؤخرًا.

أعتقد أن الطريقة التي سأقترب بها من هذا هي الحفاظ على عدد منفصل أو علامة في مكان ما للإشارة إلى ما إذا كان الكائن الموجود في ذاكرة التخزين المؤقت يستخدم أم لا. يمكنك بعد ذلك التحقق من ذلك عند الانتهاء من كائن ، أو مجرد تشغيل فحص كل ثوانٍ لمعرفة ما إذا كان يجب إصداره أم لا.

أود تجنب أي حل يتضمن إطلاق الكائن قبل إزالته من القاموس (باستخدام NSValue's valueWithNonretainedObject: سيكون طريقة أخرى لإنجاز هذا). سيؤدي ذلك فقط إلى مشاكل على المدى الطويل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top