Почему подпредставления NSView не отправляются сообщение выпуска, когда приложение Какао завершается?

Здесь я собираюсь показать вам, как создать кнопку BROWSE, при нажатии на которую она откроет SD-карту, выберет файл и в результате вы получите имя файла и путь к файлу. из выбранного:

Кнопка, по которой вы нажмете

browse.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        Uri startDir = Uri.fromFile(new File("/sdcard"));
        startActivityForResult(intent, PICK_REQUEST_CODE);
    }
});

Функция, которая получит имя файла и путь к файлу

protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if (requestCode == PICK_REQUEST_CODE)
    {
        if (resultCode == RESULT_OK)
        {
            Uri uri = intent.getData();

            if (uri.getScheme().toString().compareTo("content")==0)
            {
                Cursor cursor =getContentResolver().query(uri, null, null, null, null);
                if (cursor.moveToFirst())
                {
                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
                    Uri filePathUri = Uri.parse(cursor.getString(column_index));
                    String file_name = filePathUri.getLastPathSegment().toString();
                    String file_path=filePathUri.getPath();
                    Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
                }
            }
        }
    }
}
7
задан e.James 27 June 2009 в 16:25
поделиться

3 ответа

Я разобрался. Решением было создать и выпустить мой собственный NSAutoreleasePool в методе applicationWillTerminate: .

Подробности:
Глубоко в недрах NSView dealloc , выполняются всевозможные действия для удаления представления и всех его подпредставлений из цепочки респондента, настройки следующего ключевого представления, отправки сообщений делегатов и т. Д. Где-то в этом коде каждое подпредставление отправил сообщение сохранить , а затем отправил сообщение autorelease . (Фактически, каждое подпредставление сохраняется и автоматически запускается дважды - см. Подробности ниже). Это нормально, но вот неприятность: когда подвиды отправляют сообщение autorelease , они добавляются к любому NSAutoreleasePool , который оказывается активным в этот момент времени, и хранятся до тех пор, пока этот конкретный пул не выйдет из области видимости. В случае завершения приложения, пул, в который они добавляются, создается автоматически во время каждой итерации основного цикла событий приложения, , и этому пулу никогда не отправляется сообщение release , потому что приложение является собирается выйти!

Результаты экспериментов:
Я добавил несколько сообщений журнала в init , keep , release и методы autorelease для MyView , все они имеют код, похожий на этот:

NSLog(@"[%@ retain]:  count = %d", [self name], [self retainCount]+1);
return [super retain];

Я также зарегистрировал { } вокруг кода для dealloc чтобы я мог видеть, когда происходит волшебство.

6
ответ дан 7 December 2019 в 01:25
поделиться

Это не просто просмотры. Это все. Я не думаю, что даже объект NSApplication освобождает себя.

На самом деле, я почти уверен (но не уверен на 100%), что ответ на мой вопрос №1 таков: «Поскольку выпуск подпредставлений не требуется, когда приложение собирается завершить работу ».

Я тоже так считаю.

Если вы хотите, чтобы ваш настраиваемый граф объектов был выпущен при выходе, сделайте его владельцем делегата вашего приложения и освободите другие объекты верхнего уровня в applicationWillTerminate :. Пока вы правильно управляете всеми своими владениями и освобождаете каждый отдельный пользовательский объект верхнего уровня из этого метода, все ваши пользовательские объекты, включая представления, умрут.

Примечание: я не пробовал смешивать это с Core Data . Это может или не может быть возможным сделать это с вашими управляемыми объектами. Я не

3
ответ дан 7 December 2019 в 01:25
поделиться

В коде, который вы представили, вы добавляете подпредставление к ivar под названием «представление». Это то, что вы действительно сделали, или это просто из-за копирования кода на вопрос?

Я спрашиваю об этом, потому что если я создаю IBOutlet для представления содержимого главного окна и запускаю ваш код, он делает то, что вы говорите. Но если я добавляю локальную переменную myView в parentView, она освобождается:

begin
init <MyView: 0x174460>
init <MyView: 0x174770>
run
quit
dealloc <MyView: 0x174460>
end
dealloc <MyView: 0x174770> 

Вдобавок оказывается, что вспомогательные представления автоматически освобождаются (добавление сообщения журнала для автозапуска это доказывает).

1
ответ дан 7 December 2019 в 01:25
поделиться