Кто-нибудь наверняка знает, действительно ли CGDataProviderCopyData () копирует данные? Или он просто создает новый указатель на существующие данные?
Это одно и то же. Указатели являются адресами памяти; по определению, если у вас одни и те же данные по двум адресам , это одни и те же данные в двух местах , поэтому вы должны были скопировать их (либо с одного на другой, либо на оба от общего происхождения).
Итак, давайте переформулируем вопрос соответственно:
Или он просто копирует существующий указатель?
Кварц не обязательно может сделать это, потому что поставщики данных не обязательно предоставляют существующий указатель , поскольку вместо них они могут быть реализованы как по существу потоковые (последовательные) поставщики.
А как насчет провайдеров прямого доступа? Даже тем, кому не нужно выкашливать байт-указатель ; поставщик может просто предложить доступ к диапазону по требованию .
Но что, если он предлагает указатель байта? Ну, документация для этого гласит:
Запрещается перемещать или изменять данные поставщика, пока Quartz не вызовет вашу функцию CGDataProviderReleaseBytePointerCallback
.
Так что, возможно, Кварц мог повторно использовать указатель. Но что если вы освободите провайдера данных (вызывая ваш обратный вызов ReleaseBytePointer
) до того, как освободите данные?
Это все еще может быть безопасно, если Quartz реализует частный пользовательский подкласс CFData или NSData, который либо реализует сбой, либо принимает на себя задачу вызова ReleaseBytePointer
, так что если вы создаете провайдера прямого доступа и создаете из него CFData и освободив провайдера, вы все равно можете использовать объект CFData.
Но это много если. Они , вероятно, просто создают простые старые (bytes-copying-at-time-time) CFData, что делает их действительными проблемами производительности.
Профилируйте это и посмотрите, сколько боли это причиняет вам. Если вам нужно о чем-то беспокоиться, тогда вам нужны некоторые решения:
- Вы могли бы просто реализовать
ReleaseBytePointer
как неиспользуемое (пустое тело функции) и освободить байты по отдельности, обязательно сделав это после освобождения как поставщика, так и данных. Теоретически, предотвращает выход байтов из-под CFData, если он использует оригинальный указатель байтов, а Quartz не реализует пользовательский подкласс CFData. Немного волосатый К сожалению, Apple не может полагаться на то, что вы делаете это, поэтому я сомневаюсь, что это действительно поможет.
- Вместо этого обрабатывайте NS / CFData напрямую. Создайте провайдер данных только для того, чтобы передать его в Quartz, а затем отпустите и сразу же забудьте об этом (не владейте им самим).
- В зависимости от ваших потребностей, вы можете предпочесть сохранить структуру обратных вызовов в переменной экземпляра и вызывать их напрямую для копирования частей данных. Конечно, если это решение работает для вас, у вас все равно не будет проблемы, описанной выше, так как вы не создаете провайдера данных с прямым доступом «здесь вы можете иметь мой указатель байтов».
В документации для CGDataProviderCreateWithCFData
не говорится, возвращает ли он провайдер данных с прямым доступом или нет, поэтому вам придется ошибиться, если вы так создаете провайдера данных.