Managing an enum within a PFObject - iOS Swift/Parse - ios

I'm new to Parse and Swift.
I have an app where people play against each other.
I want to create an activity feed where game results, cheers, heckles (anything really) can show up in a list.
My thought is to create an Activity class that subclasses PFObject and I'd like to have an enum ActivityType to determine what kind of Activity is being created.
Can I set up the Activity object in Parse and the PFObject in Swift so that each Activity is set up with the correct ActivityType?
My thinking is that I need a "Type" column in Parse that's just a number and an init method that reads that number and sets the correct type.
Does that sound about right?
Thanks

You could use a type column in parse, though I'd expect each of your different kinds of feed item to be different classes in parse as they all have different data and relationships, so you could use the class type (name).
In either case this is just a way to identify the type coming from the server. Once you have that you want an organised and common approach to displaying the feed items. To do that you should have a protocol which defines what a feed item needs to provide in order to be displayed on the feed. Then you have a set of classes, each conforming to that protocol, and each dealing with one of the different types of feed item to 'mutate' them into the common format for display.
Using an enum in your app would work, but it could lead you to have one big switch statement dealing with everything. So long as you just use the enum and switch to deal with deciding which class to create to handle the feed item then your code should be well structured.

I've solved this problem. It was 'free' functionality from Parse. I think first of all, you should consider subclassing PFObject (for many reasons). Once you do this, all you have to do is add the enum as a property to your subclass. It's taken care of automatically by Parse.
Parse knows how to convert to NSNumber and vice versa for an enum, no need to worry about that.
Note, in your .m file:
#implementation MyParseObjectSubclass
#dynamic aPropertyIWantPersisted; // declare your properties as dynamic to be managed by Parse
#synthesize aLocalTransientProperty; // if you have transient properties that you don't want persisted to the server.
+ (void)load
{
[self registerSubclass];
}
+ (NSString*)parseClassName
{
return "MySubclass";
}
#end

Related

Sending a parameter (or get the key) with inAppSettingsKit when initialising custom controller

I'm trying to initialise a custom viewcontroller and send a parameter with it but can't figure it out.
To sketch an idea:
I want to have different settings per sport (walking, running, ...) and save those in core data on the custom viewcontroller.
To know to which sport the settings belong to I need to know what sport the user tapped to get to that screen. I was thinking about doing this by sending a parameter, using a custom init for each sport or by getting the key. All of which I can't figure out.
I've looked into this issue and tried to do it like this: (item 4)
But that doesn't work, according to the IASK docs I think I also need to specify a file, but what file?
The selector must have two arguments: an NSString argument for the file name in the Settings bundle and the IASKSpecifier.
I've tried setting a File field and tried different values but without success.
I'm seriously lost here, if it's possible to get the key of the item that initialised the controller ("running" for item 4 for example) that would also be good.
I've tried so many different things I'm losing my mind, I'm obviously doing something very wrong but I have no idea what it is.
You don't need to specify an IASKSpecifier key in your Settings.plist. The way this works is you implement
SettingsPerSportViewController.m:
- (id) myinit:(NSString*)file specifier:(IASKSpecifier*)specifier {
if ((self = [super init])) {
// setup your VC
if ([specifier.key isEqualToString:#"tennis"]) {
// custom stuff for tennis
}
}
return self;
}
However, this means you build the settings view controllers for your sports on your own and don't use IASK for that.
If all sports share the same settings and you want to use IASK to generate the settings view controller, you could implement a custom settings storage and use the same Sport.plist for all sports. Your custom settings storage could then load from and save directly to Core Data. A sport property would then route the load and save operations to the right Core Data context or table.
At the root level you could have a simple static view controller that sets up and pushes an IASKAppSettingsViewController for each sport with the settingsStore property set to your custom storage subclass and the sport property set according to the selected sport.

How to iterate over the properties of my models in objective c?

I want to iterate over the properties of my models in Objective-C. I tried this. Created PropertyUtil class with method classPropsFor:(Class)klass. Please find the attachment. Used objc/runtime.h. The code which I got from the net. In my viewcontroller I am doing this. [PropertyUtil classPropsFor:[self.user class]];. self.user is User model class. What I want to know is how can i iterate over the properties of my models, let's username, password and those values.
You may want to manually list all properties your model has.
Just add a method to your model:
+(NSArray*) propList {
return #[#"prop1", #"prop2"];
}
Then just use key-value coding to get the value
[someObject valueForKey:#"prop1"];
That's pretty straight and simple way if you wish to avoid Obj-C meta functions. Since you add your properties manually anyway, you may also add them in your list as well.
That's of course, if you don't have a large amount of models already and you wish do them all at once.

Iterate through all objects that have been encoded using NSCoding iOS

I have a class (SpendrList) that has an NSMutableArray property that acts a list that the user saves multiple things to while using an app (it's a datasource for a UITableView). Using the NSCoding protocol, I encode/decode this class as needed.
This works fine, as the array property holds list items from a class I created, SpendrListItem, (also adhering to NSCopying protocol) and I encode it as the user makes any edit in the UITableView, like so:
NSURL *dataFile = [FileSystemHelper pathForDocumentsFile:kFilePathList];
NSString *filePath = [dataFile path];
[NSKeyedArchiver archiveRootObject:_list toFile:filePath];
Right now, I am just dealing with one list so this was relatively easy to set up after a few tutorials on NSCoding. Now, what I want to do is code in support for the user to have multiple lists in my app.
I have a collection view in another ViewController set up where I want to display all the lists created, and I am wondering if I can iterate through all objects I have encoded contained in the app sandbox.
Psuedocode:
for (encodedObject in App Sandbox){
if([encodedObject isTypeOfClass: SpendrList]){
//Add to iVar array to show in collection view
}
}
Multiple Lists [in isolation]?
Sounds like documents. Specifically, if you have multiple chunks of data that are held in relative isolation, even if identical in structure, you should likely manage and persist them separately. Potentially, you might have a master document that keeps track of the inventories of other documents.
That is, persist those lists to separate files.
Fortunately, iOS has an entire infrastructure for helping you with this; see UIDocument.

How do I persist graphic data in iPhone/iPad?

I am making an iPad app where the user can create graphic content with images and text. I am storing this in memory in an array of custom UIView subclasses. Each of these view subclasses can have any number of subviews containing images or text.
Now I need to save these in the device. As I explore, there seem to be many ways to do this and would like to know what would be the best for this case.
It looks like you are asking for the architectural design of what will end up being a Drawing app. This means that best it's really dependent on you specific use-cases, and cannot be answered completely unless you provide a quite detailed list of requirement.
But in general, I could try to give you some general tips that will have anyway to be integrated with you own specific nitty-gritty implementation.
This description will make some assumptions regarding the basic use cases that an app like this may need:
The user can create an image using multiple tools to achieve the result. These can be anything, from a brush to a textfield and so on
The information regarding which tools have been used to create the picture and how this tools have influenced the picture current look, can be saved in order to allow the user to later on edit the picture
Said this, the main problem is: how to store your drawing state in order to recover it later?
There are indeed many ways to achieve it, but I believe 2 of them are what would be considered "clean and famous enough".
NSKeyedArchiver
This wouldn't be my favourite (difficult to maintain), but if you have to deal with UIView, it's probably gonna be the quickest.
The NSKeyedArchiver is
.. a concrete subclass of NSCoder, provides a way to encode objects
(and scalar values) into an architecture-independent format that can
be stored in a file.
It implements the Memento design pattern and It's the same pattern described in Pro Objective-C Design Patterns, that, incidentally, presents a case study that has many of the most important use-cases matching yours:
A drawing pad allows scribbling with the user’s finger.
[...]
It allows the user to save a scribble.
It allows the user to open a saved scribble.
[...]
It's an app for having a drawing pad, where you can draw lines with your finger.
Yours looks like a simplified version of this, with images and texts instead of the scribble.
So, what's the pro, in this specific case, of using the NSKeyedArchiver? The UIView already implements the NSCoding protocol, the one needed to archive the object. So, for most of the information you need to store (coordinates, frame size, background color ...), you don't have to do anything but... archiving the object.
For any additional attribute on top of the UIView (for instance: the local path of your image, because archiving an UIImageView is really expensive), you can take a look at this article that explains with proper detail what you have to do in order to take advantage of the NSKeyedArchiver to store your object states.
This all boils down to:
implement the NSCoding protocol for each of the tools your drawing app is gonna provide
keep track of the subviews that the user create (images, text...)
when the user hit "save", loop through them, create an archive, and store them to a sensful path. The first component of the path could be the name of the Drawing, the second one the name of the tool and the third an id for each time the tool has been used. Like
// A mountain image
/<path to you Document dir>/Mountains/Image/1
// A sun
/<path to you Document dir>/Mountains/Image/2
// The text "Mountain is awesome"
/<path to you Document dir>/Mountains/Text/1
Then of course you will have to save the list of Drawing names somewhere, either in a plist file or in a NSUserDefault, so to be able to show them to the user in case they want to restore them for editing.
Core data
This is probably the cleanest and more maintainable way to store you object states, but is gonna be a bit tough and cumbersome, in particular if it's the first time you use core data. I'm not gonna dig into Core Data, but I can give you some guidelines of the whole procedure. Basically:
You create a db schema that represents each of the tools your are gonna let the user use. Like: a table for Image, a table for Text and so on
On each table you put the attributes you need to remember (location, text color for "Text", image URL for "Image" and so on)
You create a table for the Drawing that the user create, with a 1-many relationship to the tool tables. This relations represents the object shown in the drawing.
Initialize you drawing canvas and each component according to what's stored in the db
Every time the user hit "save", create or update the proper db tables in order to reflect the current drawing configuration in the storage.
One of the advantages of this approach is that, if one day you want to change a tool component property or add new ones, you can take advantage of schema migrations in order to deliver backward compatibilities with new updates. So the users will still be able to use their old drawings.
And so on and so forth...
These are two of the zilions of possibilities. You could use also use:
NSUSerDefault to store states, that I suggest to avoid. It's gonna be really hard to maintain
Mix of the two aforementioned techniques
If you plan to deliver >= iOS6 only support, you can check this
etc
The two I described are just what I feel are the usual and most discussed way of doing this. You find them in books, tutorials and they let you quite a lot of flexibility for anything you have to do.
If you need more explanatory links, let me know.
As I mentioned in a comment, you might want to look into iOS's state preservation API's. However, if you want to build your own system to do this it'd be pretty simple using some clever categories and dictionaries. Then you can serialize/deserialize your dictionaries using NSKeyedArchiver and NSKeyedUnarchiver.
eg:
#interface UIButton (MyAppCategory)
- (NSDictionary *)viewProperties;
- (void)configureFromProperties: (NSDictionary *) properties;
#end
#implementation UIButton (MyAppCategory)
- (NSDictionary *)viewProperties {
return #{ #"class" : NSStringFromClass([self class]),
#"frame" : [NSValue valueWithRect:self.frame],
#"titleLabelText" : self.titleLabel.text,
// etc...
};
}
- (void)configureFromProperties: (NSDictionary *) properties {
NSValue * value = properties[#"frame"];
if ([value isKindOfClass:[NSValue class]]) {
self.frame = value.rectValue;
}
NSSString * titleLabelText = properties[#"titleLabelText"];
if ([titleLabelText isKindOfClass:[NSString class]]) {
self.titleLabel.text = titleLabelText;
}
}
#end
// replicate the above pattern for other view objects you need to support
#implementation MyViewFactory
- (UIView)recreateViewFromProperties: (NSDictionary *) properties {
NSString * className = properties[#"class"];
if ([className isKindOfClass:[NSString class]]) {
Class viewClass = NSClassFromString(className);
id viewObject = [[viewClass alloc] init];
if ([viewObject respondsToSelector:#selector(configureFromProperties:)]]) {
[viewObject performSelector:#selector(configureFromProperties:) withObject:properties];
return viewObject;
}
}
return nil;
}
// exercise for the reader: iterate your views and use the viewProperties: method to collect your views' configuration info...
#end
If you want to allow for future session editing and loading etc. I would suggest designing a data structure and create a core data model out of it.
Some structure holding the session metadata e.g. sessionID, creationDate, dictionary of key:imageName value:imageFrame (CGRect wrapped in NSValue, use setObjectForKey).
Loading images for the session would work by calling the keys into an array using e.g.[sessionImageDictionary allKeys], iterating through the keys and asynchronously (NSOperationQueue with maxConcurrentOperationCount) loading the image at some Macro path to e.g. the library directory, and appending the key, which is the imageName.
In the same iteration you can set its frame by calling [sessionImageDictionary valueForKey:[arrayOfKeys objectAtIndex:currentIteration]; Converting the previously stored NSValue back to CGRect.
The datastructure all depends on the amount of features you want, but the good thing is it allows for expansion and with core data as the backing store, you could do things like sync between devices, enable multiple sessions for loading and saving like a "My projects" feature. It will help if lets say the user builds up a library of images (all stored in your apps library directory) and then the user uses the same image in the same session or in multiple sessions, only one copy of the image needs to exist, with zero duplicate write outs to disk and the core data object will have the filename stored in the session.
The most important part would be building a correct Core-Data model and writing an extractor that can accept these custom subclasses, strip out the data to create, populate and save an NSManagedObject to the persistent store.
Your best option is to use UIDocument with NSFileWrapper folder. Then you can store all your files in one folder which is saved automatically when the contents change.
Refer to:http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011149-CH1-SW1

Unsure of how to manage data in ios app

I hope this question isn't too general/ambiguous...
I'm writing an iphone quiz game app and am having trouble figuring out the best way to handle data. Currently I am thinking of having a single Model class that holds an array of "User" classes which each have an array of user-specific "Question" classes. I'd like to be able to access the overarching Model from any of my view controllers, but that means I'll probably have to pass the model object to any new view controller, use a singleton, or do something else. What is the best way to access my Model object from other classes? Another factor I'm not sure about is being able to save the data - would I have to use Core Data/SQLite to save my single Model object, or is there a simpler way?
I'd start by designing a schema using CoreData. IMO, its best to start out using CoreData because then you'll never have to convert your data layer to CoreData, in the event that your app scales beyond a simple object or two.
The other route would be to create a web service that returns your data... so you just call the service and it returns a collection of user objects. You can either send down the entire object graph with the questions, or create another service to return a collection of questions for a specific user. If you have a web server handy, this method scales the best because you don't have to rely on app updates to get new questions into your system. I would still use CoreData to cache the results... so that way you're not downloading the same information all the time.
So when it comes to accessing CoreData objects, I use a repository class that's a singleton. This makes it easy for any view controller to grab an instance of the repository and get some data. Here's what something like that might look like;
[[Repository defaultRepository] findFirst:[User class]
where:#"name == 'John'"]
There's a lot of redundant code to fetch data so wrapping that up in an object will help get all that nasty code, like predicates and sorting, out of your view controllers. You can see where I leverage a va_list in the where clause so I can inject that string right into my predicate. Here are some other methods you could implement:
- (NSArray *) findAll:(Class)entity
sortByKey:(NSString *)key
ascending:(BOOL)ascending;
- (NSArray *) findAll:(Class)entity
sortByKey:(NSString *)key
ascending:(BOOL)ascending
where:(NSString *)format, ...;
- (id) findFirst:(Class)entity
where:(NSString *)format, ...;
I'm not sure if this is the preferred way, but I've had a lot of success with this method. Hope this helps!
Check this link, this will help you a lot
Link: http://mobile.tutsplus.com/tutorials/iphone/iphone-sdk_store-data/
This cover 4 major ways to store data in iPhone with sample code.
1) NSUserDeafult
2) Property Lists
3) SQLLite
4) Core Data

Resources