Как сохранить состояние с помощью CALayers?

У меня есть простое приложение для iphone, которое рисует блоки, используя подкласс CALayer, и я пытаюсь найти лучший способ сохранить состояние или сохранить созданные в данный момент слои.

Я попытался использовать ответ Брэда Ларсона из этого предыдущего вопроса о хранении настраиваемые объекты в NSUserDefaults, которые работали для сохранения моего подкласса CALayer, но не для его базового состояния, такого как геометрия и цвет фона, поэтому они были там, но не отображались при перезапуске.

Я сделал объявленные переменные экземпляра соответствующими протоколу NSCoding, но не знаю, как заставить свойства CALayer делать то же самое без повторного объявления всех его свойств. Или это вообще не лучший / правильный подход?

Вот код, который я использую для архивации массива слоев:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:viewController.view.layer.sublayers] forKey:@"savedArray"];

А вот код, который я использую для перезагрузки моих слоев в -viewDidLoad:

    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];

NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];

if (dataRepresentingSavedArray != nil) {

    [self restoreStateWithData:dataRepresentingSavedArray];

И в -restoreStateWithData:

    NSArray *savedLayers = [NSKeyedUnarchiver unarchiveObjectWithData:data];

if (savedLayers != nil) {

    for(layer in savedLayers) {

        [self.view.layer addSublayer:layer];

    }

    [spaceView.layer layoutSublayers];      
}

person Joe Ricioppo    schedule 21.07.2009    source источник


Ответы (2)


Какао (и Какао Touch) в основном основаны на организации модель-представление-контроллер. CALayers находятся на уровне просмотра. Это приводит к двум вопросам:

  1. Какую часть вашей модели ваш слой представляет пользователю?
  2. Как сделать так, чтобы эта часть модели сохранялась?

Ответы на эти вопросы - ваше решение.

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

person Peter Hosey    schedule 22.07.2009
comment
Смысл Питера здесь ключевой. Сосредоточьтесь на данных, которые вы хотите сохранить, а не на реализации CALayer. CALayer должен отображать ваши данные, а не быть вашими данными. Когда вы создали класс данных, его сохранение должно быть довольно простым, и когда вы загрузите его снова, вы можете легко регенерировать новый CALayer для его отображения. - person Rob Napier; 22.07.2009
comment
Вы начинаете правильно, но затем, кажется, начинаете вставлять детали презентации в свою модель. Я не уверен, что это за приложение; если это графическое приложение, то, возможно, «рамка» является законной частью модели. В остальном я сомневаюсь. Если прямоугольники фрейма, радиусы углов и цвета не являются частью данных, которые пользователь использует в вашем приложении для обработки и редактирования, то они не принадлежат модели, и вы должны оставить их для обработки вашему подклассу CALayer. У вашего подкласса CALayer должно быть еще одно свойство, с помощью которого вы даете слою объект модели, который он должен представлять. - person Peter Hosey; 24.07.2009
comment
Контроллер владеет и создает как объекты модели, так и объекты представления (слои), и передает каждый объект модели представлению (слою), которое будет отображать его. Контроллер и представление (слой) используют один и тот же объект модели, и каждый из них сохраняет его. - person Peter Hosey; 24.07.2009
comment
«У меня почти все заработало, за исключением того, что UIColor не будет успешно кодировать, архивировать, а затем разархивировать. Есть ли способ архивировать структуры, чтобы я мог просто сохранить CGColorRef, не преобразовывая его в UIColor? » CGColor - это не структура. В документации UIColor говорится, что он соответствует NSCoding, поэтому любой архиватор и разархиватор, который вы используете, должен иметь возможность его кодировать. Если это не работает, вам следует сообщить об ошибке в RadarWeb. - person Peter Hosey; 24.07.2009
comment
Хорошо спасибо. Я запишу ошибку на UIColor. Но что такое CGColorRef, если это не структура? и есть ли способ его спасти? - person Joe Ricioppo; 25.07.2009
comment
Это объект Core Foundation. Они взаимозаменяемы с объектами Какао; вы можете поместить их в массивы NSArrays (которые также являются CFArrays), посылать им сообщения retain, release и autorelease и передавать их %@ форматировщику stringWithFormat:, CFStringCreateWithFormat и NSLog. Однако они не соответствуют NSCoding, поэтому вы не можете архивировать их напрямую. - person Peter Hosey; 25.07.2009
comment
Спасибо, Питер. Я еще не дал подклассу CALayer экземпляр модели, но это то, что у меня есть, и кажется, что он должен работать, если я делал это правильно. stackoverflow.com/questions/1182691 / - person Joe Ricioppo; 25.07.2009

Чтобы быть точным, согласно документации Apple, CALayer на самом деле является моделью, а не представлением в шаблоне MVC.

«CALayer - это класс модели для объектов дерева слоев. Он инкапсулирует положение, размер и преобразование слоя, которые определяют его систему координат».

Вид за слоем на самом деле является видимой частью узора. Слой нельзя отобразить без заднего вида.

Мне кажется, что он должен быть вполне законным кандидатом на сериализацию данных. Взгляните на расширения KVC для CALayer. Особенно посмотрите на:

- (BOOL)shouldArchiveValueForKey:(NSString *)key
person Matt Long    schedule 26.07.2009
comment
Этот комментарий устарел :-). Последний iPhone SDK также поддерживает архивирование CALayers. - person jarjar; 13.09.2010
comment
CALayer - это класс модели для деревьев слоев, это верно, но это никоим образом не делает его частью модели MVC-шаблона. Модель в MVC - это только данные и логика вашего приложения. - person Ahti; 19.02.2013