How do I use Core Data with the Cocoa Text Input system? - objective-c

Hobbyist Cocoa programmer here. Have been looking around all the usual places, but this seems relatively under-explained:
I am writing something a little out of the ordinary. It is much simpler than, but similar to, a desktop publishing app. I want editable text boxes on a canvas, arbitrarily placed.
This is document-based and I’d really like to use Core Data.
Now, The cocoa text-handling system seems to deal with a four-class structure: NSTextStorage, NSLayoutManager, NSTextContainer and finally NSTextView. I have looked into these and know how to use them, sort of. Have been making some prototypes and it works for simple apps.
The problem arrives when I get into persistency. I don't know how to, by way of Cocoa Bindings or something else, store the contents of NSTextStorage (= the actual text) in my managed object context.
I have considered overriding methods pairs like -words, -setWords: in these objects. This would let me link the words to a String, which I know how to store in Core Data. However, I’d have to override any method that affects the text - and that seems a little much.
Thankful for any insights.

NSTextStorage is just a subclass of NSMutableAtrributedString which support the NSCoding protocol so you can save it in Core Data as a transformable attribute using the default NSKeyedUnArchiveFromData transform.
I'm pretty sure that holds true for all the other classes you might want to save with the possible exception of the views. (I've never tried to store them in Core Data buts its theoretically possible to do so.)
Any class that implements/inherits NSCoding or has a initWithCoder: method can be stored in code data as a transformable attribute.

I suggest binding the value binding of a text view to a string attribute of one of your model entities, or the attributedString binding to a transformable attribute. This hooks up the view to the model without you having to pass text back and forth yourself.

Related

Where is representative data placed in the MVP or MVC pattern?

In the MVP and MVC pattern you want to clearly separate the View from the Model.
But to display stuff like Icons, Animations that should play when something happens etc., the Model needs to tell the View how it wants to be represented. For example the icon on a button that selects an element.
Thus I think that stuff like Images, Animation Frame Data etc. should be part of the Model as the elements of the Model need to define this. But I also feel like this should not be the case. As such the only thing I can imagine is having a huge Mapping stored somewhere that maps types of the model to representative data. That seems like a huge anti-pattern to me.
How would you structure this stuff in a project? Where is the data of "how should it look" be stored? Inside the Model, inside the Presenter (a Mapping) or inside the View (a Mapping). Maybe I am missing something crucial here.
To clarify where this is coming from:
Consider you have objects that get represented by icons in a list. These objects all have a common supertype but each differ in details and thus should be represented by different icons. Moreover, maybe you implemented everything as a common type and define it's whole behavior just during construction or setting stuff up during runtime, so you do not even have a way to differentiate between icons to display via type. As such I would deem these objects need an accessor like "getImage" to get the representation they would like to have in the GUI. But having the image be part of the model seems wrong.
To present a common way to form an answer, the imaginary project may be structured in the following directories:
src/model/
src/view/
src/presenter/
Where would each type/class with what methods be located?
How would you structure this stuff in a project? Where is the data of
"how should it look" be stored?
This is where I use a ViewModel. You map your Model to the ViewModel and use the ViewModel to represent what properties get displayed. You can tailor the ViewModel to:
Style/css the property,
Combine properties,
Validation logic,
Change how the property is displayed and more.
Where would each type/class with what methods be located?
src/viewModel

Do I need to use a delegate to maintain the MVC pattern when accessing NSUserDefaults?

Still on assignment 4 of cs193p. - http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/assignments/Assignment%204_2.pdf
I've fully (ish) implemented the displaying photos from a list of places.
I'm adding the second tab of the application (required tasks 10 & 11) , which is to generate and display a list of the 20 most recent photos viewed in chronological order.
My question relates to the MVC pattern and setting/accesing NSUserdefaults.
Basically, anytime a photo is viewed, a property list stored in NSUserdefaults needs to be updated.
When selecting the "recent photos" tab, those values need to be read and displayed, so that the user can select a recently viewed photo, and then view it by selecting it.
I think I can implement this quite easily from a writing lines of code and it will probably work point of view.
I've seen this question: CS193P UITabBarController MVC Help on Assignment 4 which is kind of related, but doesn't really address my more theoretical question about the nature of the pattern.
My question is more about the MVC pattern.
In the lecture, when he demonstrated this with favourite graphs, from the previous calculator assignment he used a delegate to communicate between the favourites list view controller and the graphviewController (see diagram on slide 64 of lecture 9). http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/lectures/Lecture%209_1.pdf
I'm trying to work out if I need to do something similar to avoid breaking the MVC pattern, or if I can just use NSUserdefaults in both the viewWillLoad of my imageViewController to add a photo to the favourites and and then in my setter in RecentImagesViewController. I know NSUserdefaults is designed for persistence, it just feels a bit like I"m using a global variable.
I realise this question is worded in a way which makes it difficult to follow if you aren't familiar with the cs193p course - sorry.
Thanks for any advice!!
I don't think you have to transform something rather simple in something complex. You are storing the favorites using the NSUserDefaults and that's it. The place where you are using might not be the best (I am not saying the viewWillLoad is a bad place, I don't know your code), but I don't think you need a delegate to just update the NSUserDefaults. Botton line, don't forget the KISS principle. :)
Well, it probably feels like you're using a global variable because the user defaults themselves are a global concept. And they should be. You don't want different parts of the app operating on unsynchronized versions of user preferences.
But, if you use the term variable in the sense of an old C/C++ global static piece of data, then, no ... that's not what it is. NSUserDefaults was written by Apple to be a nice tidy class that encapsulates the user default data. The fact that you use [NSUserDefaults standardUserDefaults] to access something like a singleton instance (not sure if that's how Apple chose to implement it) still doesn't mean it's a true global variable.
I agree with Jacky Boy that keeping it simple is best, but your question is really asking whether doing it the way you are is a violation of the MVC pattern (and adhering slavishly to a pattern is not always going to make your code the best). That depends on what you consider the model to be. I could justify saying that Apple built NSUserDefaults to be a model layer encapsulation of the preferences data. So, there you have your model layer, and your controllers should be able to use it.
Or do you feel the need to write the entire model layer yourself, in which case your model layer would just have a wrapper for NSUserDefaults. That would seem like overkill for most situations.
Here is maybe one situation that could warrant it. If you have a lot of preference data that seems logically related, but some of it is not appropriate for NSUserDefaults. Perhaps it's a lot of binary data, stored in a hierarchy of objects, and you want to persist it with Core Data. But, it still seems logically related to what you're keeping in NSUserDefaults. Maybe then, you decide to write your own model layer, that encapsulates both the Core Data and NSUserDefaults data. Your view controllers could then use that directly.
But, generally, I think iOS is well designed to have whoever needs to just use the standardUserDefaults object directly.
If I understand the question correctly, it sounds like the setting/loading should be occurring from the appropriate view controller. Creating a delegate (which may or may not be a singleton) that you can call from each of the different tab's view controllers will help prevent you from duplicating code.

iOS: How to save a custom object that is created in an app

I've been reading up on saving objects, preserving state etc, but I'm still a little confused on the route I should take when saving objects that are created from my app. I have built an app where a user can create a Radio Station with the Genre, name and frequency. Once a user hits save, a "RadioStation" object is created using a custom class and is stored in an NSMutableArray that is placed in the RootViewController. While RadioStation objects can be stored in this array and are displayed correctly in the table view, it's obvious that once the application quits, these are no longer going to be held by the application.
At this point I'm not sure how I should begin to architect this design. Do I need to set up a plist? Should I use Core Data with a SQLite DB? Do I need to research iOS object serialization for both these scenarios? Or is there an more straight forward way that I'm not aware of?
There are three ways to persist data locally:
Store objects in a database using managed objects or SQLite
Store objects in a file in the sandbox using various classes' writeToFile
Store the data in NSUserDefaults
How you persist your object data depends on how you're using it, and what type of data you're saving. CoreData makes sense if you have a lot of objects of the same type and SQL's search and sorting mechanisms would be useful. I tend to use the sandbox for very large files, eg images, sound files, and large agglomerations of data bounced through NSData. And I use UserDefaults for small amounts of data that might be considered "preferences".
You can put anything anywhere you want, and I suggest being familiar with all three mechanisms when you start a new project. Additional techniques, like using NSCoding to serialize and deserialize classes, can be used to make saving data easier. Note that once you've implemented NSCoding, you could store data anywhere and even send it over the wire.
For your RadioStation, I would personally use UserDefaults. The benefit of using NSCoding is that, once you implement initWithCoder and encodeWithCoder, you can stream a hierarchy of objects (eg an array of custom objects, each of which might contain a dictionary, array, or custom object, etc) fairly easily. If the only thing you're saving is an array of strings, then directly using UserDefaults is easy enough.
The most powerful approach is to make your custom object a subclass of NSManagedObject, and store it in an NSManagedObjectContext using Core Data. On iOS this will always use an sqlite database, on Mac OS X you can use sqlite, xml, or a proprietary binary format (smaller/faster than xml).
Depending on how complicated your data structure is, and how likely it is to change in future, this technique may or may not be too complicated for your app. It's a lot of work to setup, and the API is very complicated, but it's the best choice if you need to store tens of thousands/millions of objects in a file.
For your app, I would have a single sqlite file containing all of the radio stations in the app.
The simplest option, is to implement the NSCoding protocol in your custom object's class. Documented here:
http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html#//apple_ref/doc/uid/20000948-BCIHBJDE
The basic theory is your object writes or reads all it's data to a "coder", and then passes the coder on to any child object(s). Outside of the class, you use an "archiver" or an "unarchiver" class to coordinate everything.
Once your custom class implements NSCoding you can read/write it to the disk with:
myObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
[NSKeyedArchiver archiveRootObject:myObject toFile:filePath];
This is a very simple approach, but it has a few drawbacks, for example you will need to figure out your own way to support different versions of the file format (perhaps with a different file extension for example).
Many classes in Cocoa/CocoaTouch already implement NSCoding, so they can be written to a file in this fashion (including NSArray, NSString, NSNumber, etc).
For your app, i would use this to store each radio station in a single file. When the app launches, load all the radio stations from a directory. You should consider enabling iTunes drag/drop filesharing for your app, so users can easily share radio station files with their friends or between devices.
This would also fit in well with iCloud for syncing between devices, I haven't looked into iCloud much, but I expect one file per radio station will be the ideal way to implement iCloud syncing.
No need for such things. If you only have like one thing to save, then research this method of NSArray:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
I your user can save many radio stations, then you might want to look into CoreData, which has a bit of a curve, but ultimately will be the easiest way.

Organizing iOS project for MVC design pattern

I'm working on a multiview app for iPhone and currently have my views (VIEW) set up and their transitions (CONTROLLER?) working nicely. Now I'd like to add objects for the actual program data (MODEL).
My question is: How should I structure my data to adhere to the Model View Controller (MVC) design pattern? I know I should create separate classes to implement my data structures and that my controller classes can pass messages to them from the view, but are there any other organizational considerations I should examine? Especially those particular to Cocoa Touch, Xcode, or iOS?
Other particulars: Playback of pre-recorded and perhaps user-generated audio will also be essential. I know these are model elements, but how exactly they relate to the "V" and the "C" I'm still a bit fuzzy on. I suppose when a user action requires audio playback, the CONTROLLER should pass a message to the MODEL to ready the appropriate sounds, but where exactly should regulation of the playback live? In a "PlayerController" separate from the ViewController I imagine?
Many thanks and pardon my MVC noobery.
Caleb gives a good introduction and overview of how to think about the problem. In your particular case, here are some of the pieces you would might have given your description:
Clip (M) - Responsible for holding the actual audio data. It would know how to interpret the data and given information about it, but it wouldn't actually play anything.
Player (V) - Actually plays a clip on the speakers. Yes, that's a kind of view in MVC. Audio is just another kind of presentation. That said, you'd never call it "PlayerView" because that would suggest it were a subclass of UIView.
PlayerView (V) - A screen representation of the Player. Knows nothing about Clips.
ClipManager (C) - An object that would keep track of all the clips in the system and manage fetching them from the network, adding and removing them to caches, etc.
PlayerViewController (C) - Retrieves a Clip from the ClipManager, and coordinates a Player and a PlayerView to display and play it, as well as any other UI elements (like a "back button" or the like).
This is just an example of how you might break it down for some theoretical audio player app. There are many correct MVC ways to do it, but this is one way to think about it.
Lord John Worfin (and, I'm sure, someone before him) said: "Character is what you are in the dark." Well, a model is what an application is when nobody is looking -- it's the data and logic that defines how the app behaves regardless of how it's presented on screen.
Imagine that you decide to add a command-line interface to your application. You'd still want to use the same structures for managing your data, and your logic for sorting, sifting, and calculating based on the data should still be the same too. The code in your app that remains important/useful no matter how the user sees or interacts with the app is the model.
A model can be very simple and made up entirely of standard objects. iOS apps are often more about retrieving, storing, and displaying data than they are about crunching numbers, so it's not unusual to have a model that's just an array of dictionaries, or a hierarchy of dictionaries that's several levels deep. If you look at Core Data's NSManagedObject class, it's similar in many respects to NSMutableDictionary. So, don't be afraid to use standard objects if they're appropriate.
That said, you can certainly also create your own model objects, and that's useful if you have certain requirements that you want to enforce on your data, or if you want to be able to derive information from the data.
Beginners often wonder how each controller gets access to the model. Some folks advocate using the singleton pattern for this, mainly because it provides a single, shared, globally accessible object. I don't recommend this. Instead, have some high-level object in your app such as the app delegate create/load the model (which will likely be a graph of many individual objects) and give a pointer to the model to any view controllers that need it. If those controllers in turn create other view controllers, they can again provide a pointer to the model (or part of it) to their child controllers.
I hope that helps.

MVC Pattern: Where does formatting/processing type work belong? (Objective-C)

As my Cocoa skills gradually improve I'm trying not to abuse the MVC as I did early on when I'd find myself backed into a hole built by my previous assumptions. I don't have anyone here to bounce this off of so hoping one of you can help...
I have a custom Model class that has numerous & varied properties (NSString, NSDate, NSNumber, etc.). I have a need to serialize the properties for transmission. Occasionally as this data is being processed for serialization a questions may come up that the user will need to respond to (UIAlertView, etc.)
Without bogging down in too many more specifics where does this code belong?
Part of me says Model because it's about persistence of data - in a way.
Part of me says View because it's another interpretation of the core data (no pun intended) contained within the model. And the user will have to interact with dialogs on occasion as data is processed
Part of me says Controller because it's managing the transformation of data between model & view.
Is it a combination of all three? If so how would communication be handled between classes as the data is being processed? NSNotifications? Direct method calls?
This may be something that you'd want to use the Visitor pattern for -- http://en.wikipedia.org/wiki/Visitor_pattern -- because you might eventually want to use different sorts of serialization for different things and you can have different visitor classes rather than a lot of special cases in the model code.
Here's a discussion of the Visitor pattern in objective-c/cocoa: http://www.cocoadev.com/index.pl?VisitorPattern
Here's an (old!!!) article from Dr. Dobbs about the visitor pattern in objective-c: http://www.drdobbs.com/184410252
The reason that the problem you're working on doesn't fit well into the MVC paradigm is that the serialization that you're doing is like a view on a stream-based rendering surface and it is displayed. Sometimes, this can be done really smoothly in the model but sometimes it's more complex and you need to look at your case to figure out which one it is.
Frequently, the transmission/web service (or whatever) code you're using will have its own handler for this data, for example ObjectiveResource adds a serialization and deserialization handler that works as an extension to NSObject that enables it to do a lot of this stuff transparently, and you might look into that code (particularly the ObjectiveSupport part) if you're trying to do this more generically.
Typically almost all application specific code belongs in the controller. The controller should interact and observe (via notification) the model and update the view as appropriate.
If you are doing model processing such that it is something that might be re-used in another app with the same model, then that processing could be in the model.
Views can be laid out in Interface Builder or created in code and/or be subclassed for custom drawing, but they should not have application logic and would not interact directly with the model.
I would suggest putting the serialising code in the model. If the process fails it can report that to whatever's listening to it (the view / controller) which can then present the UIAlertView, correct the problem and re-submit for another attempt.
I'd say in the model.
The call to serialize the data will be done by the controller. If the data cannot be serialized then the model should return an error which the controller then has to handle.