thinking about how a user can just suddenly delete their account and disappear, leaving the entire body of their work to exist solely the obscure reblogs of their followers

seen from United States
seen from China
seen from China
seen from United States

seen from United States
seen from Georgia
seen from China
seen from France

seen from United States
seen from United States
seen from China
seen from South Korea
seen from T1

seen from Malaysia
seen from China

seen from France
seen from Japan
seen from China

seen from Japan
seen from France
thinking about how a user can just suddenly delete their account and disappear, leaving the entire body of their work to exist solely the obscure reblogs of their followers
DATA PERSISTENNNNNNNNNNNCE!!!
I have waited so long for this day!!!
Remember when I started coding my German trash-sorting app back in April or May or whenever that was, last year? I ran straight up against the issue of data persistence and basically haven’t returned to it since then. But now I know how to handle the situation :D I can just put everything in a database and it will last forever, woohooooooo ~~~
A quiet week on this blog (back home, driving theory test next week, hosting people for my birthday this weekend). Mid way into learning about data persistence, I realised that for this to be even minimally functional, I would want to be able to name save files from within the game. Which requires text input. Hence my exploration of a text-based adventure tutorial! All I need from it is player input but there might be some useful info about ‘scriptable objects’ too.
Week 4 Plan
There are two pieces of the puzzle I want to understand better this week: First, the Data Persistence introduced in the Adventure Game tutorial. The ability to save networks once drawn is obviously one I want; while including it as a feature at this stage may seem premature, it will make 4edge usable as a resource long before it's viable for distribution. Moreover there is a more basic tutorial that I can use to fill the gaps, while nonetheless implementing the editor produced in the Adventure Game tutorial. Second, I would like to understand the Animator better, since this may be the key to controlling the (appearance) states of nodes. Since the point of this project is visualisation, appearance will ultimately be one of the most important things to control; I'd rather get on top of it now. Since the plan in Week 2 (and hence Week 3) was overly ambitious, this is all I'm going to set myself for this week.
DATA PERSISTENCE IN LAGOM
DATA PERSISTENCE IN LAGOM
Are you finding it difficult to understand lagom persistence? Don’t worry because help is right here. In this blog, we will learn about lagom’s persistence with the help of a simple application and also discuss its theoretical aspects. Before we begin, make sure you know about Event Sourcing and CQRS. You can read about it in details from this link .
Choosing a database
When we create any…
View On WordPress
A Possible NSUserDefaults Alternative.
It is often the case that we need to persist a few bits of info or at least a single object, like a "user". Core data is too big for this, NSUserDefaults is sometimes not the best practice use case, and does not provide compiler auto-completion. The correct way is to create a (singleton) object for the data, and use NSKeyedArchiver for persistence, which is not super fast, but is straightforward and speed does not matter for small classes like this. It is not hard to use, but there are a few things that you have to do correctly. For a quick refresher, there are lots of examples, but this one is fine
provide a method to encode each property of the object by encodeForKey by giving it an NSString key that is the same name as the property.
Provide a method to decode each property the same way.
This leads to two problems:
Must manually match the @"keyName" to the @property name. The compiler does not help you here.
Must remember to add/modify the @"keyName" every time you add/modify a property name that you want to persist.
The most tedious (and treacherous) way:
[coder encodeObject:name forKey:@"name"]; [coder encodeObject:subgroups forKey:@"jobs"]; [coder encodeObject:tasks forKey:@"location"];
The less tedious way, using an array of keys and valueForKey:
- (NSArray *)keysForEncoding { return [NSArray arrayWithObjects:@"name", @"jobs", @"location", nil]; } - (void)encodeWithCoder:(NSCoder *)aCoder { for (NSString *key in self.keysArray) { [aCoder encodeObject:[self valueForKey:key] forKey:key]; } }
The worst thing is that both still have boilerplate which is not compiler checked.
So, thinking about this, I was trying to come up with a way to use introspection to eliminate the manual entry of a key array. This led me to a Objective-C runtime method that fit the bill.
+ (NSArray *)keysFromProperties { u_int count; objc_property_t* properties = class_copyPropertyList([self class], &count); NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count]; for (int i = 0; i < count ; i++) { [propertyArray addObject:@(property_getName(properties[i]))]; } free(properties); return [NSArray arrayWithArray:propertyArray]; }
So now my encoding does not depend on any array that I must manually fill, it is just a method and looks like this:
- (void)encodeWithCoder:(NSCoder *)aCoder { for (NSString *key in [[self class] keysFromProperties]) { [aCoder encodeObject:[self valueForKey:key] forKey:key]; } }
So I can simply add object and primitive data properties directly in the @interface, and the class takes care of the rest. I get autocompletion in the compiler, so there are no strings to keep track of.
I have posted the code on Github . I would love feedback.
A Possible NSUserDefaults Alternative.
It is often the case that we need to persist a few bits of info or at least a single object, like a "user". Core data is too big for this, NSUserDefaults is sometimes not the best practice use case, and does not provide compiler auto-completion. The correct way is to create a (singleton) object for the data, and use NSKeyedArchiver for persistence, which is not super fast, but is straightforward and speed does not matter for small classes like this. It is not hard to use, but there are a few things that you have to do correctly. For a quick refresher, there are lots of examples, but this one is fine
provide a method to encode each property of the object by encodeForKey by giving it an NSString key that is the same name as the property.
Provide a method to decode each property the same way.
This leads to two problems:
Must manually match the @"keyName" to the @property name. The compiler does not help you here.
Must remember to add/modify the @"keyName" every time you add/modify a property name that you want to persist.
The most tedious (and treacherous) way:
[coder encodeObject:name forKey:@"name"]; [coder encodeObject:subgroups forKey:@"jobs"]; [coder encodeObject:tasks forKey:@"location"];
The less tedious way, using an array of keys and valueForKey:
- (NSArray *)keysForEncoding { return [NSArray arrayWithObjects:@"name", @"jobs", @"location", nil]; } - (void)encodeWithCoder:(NSCoder *)aCoder { for (NSString *key in self.keysArray) { [aCoder encodeObject:[self valueForKey:key] forKey:key]; } }
The worst thing is that both still have boilerplate which is not compiler checked.
So, thinking about this, I was trying to come up with a way to use introspection to eliminate the manual entry of a key array. This led me to a Objective-C runtime method that fit the bill.
+ (NSArray *)keysFromProperties { u_int count; objc_property_t* properties = class_copyPropertyList([self class], &count); NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count]; for (int i = 0; i < count ; i++) { [propertyArray addObject:@(property_getName(properties[i]))]; } free(properties); return [NSArray arrayWithArray:propertyArray]; }
So now my encoding does not depend on any array that I must manually fill, it is just a method and looks like this:
- (void)encodeWithCoder:(NSCoder *)aCoder { for (NSString *key in [[self class] keysFromProperties]) { [aCoder encodeObject:[self valueForKey:key] forKey:key]; } }
So I can simply add object and primitive data properties directly in the @interface, and the class takes care of the rest. I get autocompletion in the compiler, so there are no strings to keep track of.
I have posted the code on Github . I would love feedback.