Observe UIImage with KVO? - iphone

My model object has a UIImage *iconImg that is often updated asynchronously. I want to allow instances of other classes to observe any changes to myModel.iconImg elegantly. Right now, my asynchronous image fetch class takes a UIImage** (yes, ugly, but it's working). The problem, however, is that messing with the UIImage via pointers bypasses any KVO I might have enjoyed using properties, so I have to use NSNotification which I'm not a big fan of. Here are the main requirements:
I want to be able to load iconImg even when no views are ready to display it (ie no UIImageView is ready)
Ideally, only the instances that have elected to observe the specific myModel.iconImg instance will be made aware of changes (unlike with Notifications where I currently have to filter)
I have several model classes with iconImg properties that all need to work this way, not just one
I can change my image fetcher class if necessary (here's current signature):
+ (BOOL)asyncImageFetch:(UIImage**)anImagePtr withURL:(NSURL*)aUrl;
Not sure how clear that is, so let me know if I can elaborate on anything.
Thanks,
Steve

For anyone looking with similar requirements, take a look at SDWebImage (looks like Olivier Poitrey is the original author). Github repository here: https://github.com/rs/SDWebImage.
I've been using it and it's very nice.

Related

What is a good design pattern for skinning an (iphone) app?

I'm far far down the road of having built all my nice buttons and things in a XIB, and I had the sudden realization that people will pay $200 more for the lower quality laptop "Cause it's pink!" but I digress.
I need to somehow centrally control the colour scheme of my app, and change colours on the fly. I have a couple ideas, like maybe a singleton "Theme" object with a few kvo compliant properties holding theme colours and fonts, then have the view controller "listen" for changes, and re-paint everything when the theme changes.
Problems with this so far: I'd need to have a pointer to every single UI object, including things like table view cells - which seems like a pain. Another possibility would be to subclass all my themed UI objects, maybe get them to register as observers on their own, but that makes me wonder about the overhead needed for this, maybe KVO isn't even the way to go here, I don't know.
So I'm wondering if anyone could share what they've done in the past, what works and what leads to big problems?
Thanks!
Update
I ended up going with a singleton object called SkinDispatcher, which only contains a lot of properties that are meant to be observed by UIView subclasses. Then I made quick and dirty subclasses of UILabel, UIButton, UITextField, anything else I happened to use.
These subclasses each looked up their tag number and used it to register for changes to the applicable fonts and colours, in awakeFromNib.
Next I made a class specifically for loading a style, which essentially opens up a plist file full of keys holding font names and R|G|B|A colours, reads them in and sets them to the applicable property in SkinDispatcher, as determined by key name. The last step (yet to be tried) is to set an observer on the StandardUserDefaults key for skins, props to the answerer for that idea.
You already mentioned a possible approach, namely using KVO. ANother possibility is to register for a specific notification, and react accordingly when the notification arrives in your view controller.

Saving a UIView for next launch (not as an image)

I am building an app with several UIViews which are generated dynamically, based on user inputs. These UIViews may contain labels, images and text. They take some time to generate so I would like the user to be able to load them up quickly on future launches of the app without having to redraw them again. One requirement is that they need to keep their interactive state so the user can continue to edit them.
I looked into NSKeyedArchiver but this doesn't seem to support UIImage. Also, I can't save it as PNG since I would like to retain their interactive state.
Is there any way to do this?
You should consider keeping the model of your data separate from the interface. You can then use this stored model to generate the interface. I know you specifically said that you don't want to do this. However, any built in method is going to have to rebuild the UIViews in exactly the same way.
If the processing of the model data is the issue, try to come up with a way to efficiently represent the state of the interface so that you don't have to start from scratch. However, that will be a lot more work.

Should I be fetching my Core Data more often?

So right now when my app starts I get all of my data from Core Data. My data has entities of Groups and People. The Groups contain People. So as I go through the app I'm adding and deleting People and Groups.
My problem lies when I select a Group from a tableview and I pass that Group onto the next tableview. From that tableview I can press a button/row and add a bunch of People from a modal view. When I press Done from that modal view I need it to update the previous view with those new People, which it's not doing correctly.
It seems a little, for lack of a better word, wrong that I'm passing a lot of stuff around. Would it be better for me to use another fetch after I update People in a Group? From reading what other people say, then I could have different views listen for an updated Core Data and change their views accordingly.
I really hope this makes sense. I've been reading a lot to try to figure out the best approach but I'm not getting anything definite. I feel like my code is turning into spaghetti so I stopped and I'm trying to rethink it all. I'm also thinking maybe I need my very own Model class as opposed to just the classes that Core Data auto-generates.
From what you've written what you're doing sounds about right. I assume you're using a NSFetchedResultsController. Have you implemented the delegate methods outlined in the docs? Specifically, the controllerWillChangeContent: method should give you what you're after.
Regarding implementing your own NSManagedObject subclass, take a look at MOGenerator.
I would recommend NSFetchedResultsController to you. See documentation at ...
http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html
Look at CoreDataBooks example, especially at RootViewController.m at ...
http://developer.apple.com/library/ios/#samplecode/CoreDataBooks/Listings/Classes_RootViewController_m.html%23//apple_ref/doc/uid/DTS40008405-Classes_RootViewController_m-DontLinkElementID_14
NSFetchedResultsControllerDelegate can help you to update your previous view easily. As I wrote, look at sample code to see how it really works.

Very basic question about the structure of my iPhone game

I'm making an iPhone game in which I have two main views, the planning stage and the action stage. Both of these will have different graphics etc, but I'll obviously need to pass information between them. I've pretty much finished programming the planning stage, and I know how to switch between views, but I'm a little fuzzy on how exactly I should be setting the whole thing up. Should my SwitchViewController, which handles the switching between the two views, also control the passing of the game state and the game moves between the two views? Or is there a better way to do this? Thanks for reading!
It would probably make sense to package all your game information up into a single 'gameState' object, and attach that to your app delegate (or some other 'non transient' object).
If you pass it all back and forth, you can run into problems if you ever change your flow, or add a variable and forget to pass it. This approach avoids both those issues.
I would suggest setting up a sharedInstance which will allow you to use data between the two screens.

How to maintain data across object instances in Objective-C?

I've had some experience developing for the iPhone but am entirely self taught and am trying to improve my practices. This is a question that is probably pretty introductory to programming.
What is the best way (or is it possible) to maintain instance variables with values that are common to all instances of an object? Is it possible to have the creation, modification, and checking of an object and its attributes happen in different places?
Say I have an object that keeps track of the number of times a user swipes the screen. Is it possible to, say, allocate that object in my AppDelegate, and then somehow increment the count variable of that object from different view controllers?
Is it possible to define an instance variable such that it is shared across all instances of the object to which it belongs? That would solve the problem.
So far, I've just made IVARs in my AppDelegate for the things like this that I've needed to keep track of and then just accessed them like this:
((MyAppDelegate *)[UIApplication sharedApplication].delegate).instanceVariable
but I don't know if that's a good practice or not. Probably not.
Maybe this is related to global variables or singletons. Or the prefix "shared" that appears above and I've seen in other places too. I'm just looking for advice or a direction to look. I hope this question makes sense and isn't too general.
I think the question(s) you are asking involve different practices for different situations. To share data among viewcontrollers is one question with a number of solutions, one of the better ones being to use a delegate for all the viewcontrollers.
If you want to have a Class manage all its own objects, even if the objects come and go, you could do one of two things:
Make the Class have a singleton, and keep track of allocations and deallocations in order to know when it should create and then dispose of itself (if needed). This is not a bad way to do it, although it may be more work.
Create a controller class that manages your other class of objects. A good example may be a class of views, controlled by a viewcontroller class.
Let's see what other people suggest.
Matt Gallagher had post a great article on exactly that problem. You can see it at Cocoa with Love.
However, on a multiple view controllers patterns as mahboudz said, delegations is preferred.
In C++ or Java (etc), what you'd be looking for is a "static instance variable", which is exactly what you describe: an instance variable that is shared by all instances of the class. Objective-C does not have such a beast, precisely, but you can use some normal C syntax to give you something very similar.
See the bottom of this page:
http://iosdevelopertips.com/objective-c/java-developers-guide-to-static-variables-in-objective-c.html
(Copy of the code there in case the page vanishes:)
#interface MyClass
{
// ...
}
+ (NSString *)myVar;
+ (void)setMyVar:(NSString *)newVa;
#end
#implementation MyClass
static NSString *myVar;
+ (NSString *)myVar { return myVar; }
+ (void)setMyVar:(NSString *)newVar { myVar = newVar; }
#end
In this case "myVar" is global to the .m file, but because it's marked "static" (this is a C trick), the compiler limits its visibility to only the .m file that it's in. (As with anything like this, keep your eye on multithreaded access if you use that.)
FWIW, if you're building something that generally needs to be robust, a singleton-like object that everybody shares is a good way to go; you get all the normal Obj-C goodness (mem management if you want it) if you do that.
I would look into using a singleton as a resource manager - maybe the resource manager part is not needed for you, but a singleton would greatly help you.
It is definitely bad practice to use keep everything in the app delegate and access it where needed.. at the very least it means code reuse becomes tricky. If you make a new app and want to use a view or control or part of the system, you'd have to also make sure your new app delegate implements all the right selectors and properties.
Also, as your app grows you'll inevitably find your app delegate gets bigger and messier and harder to deal with.
Debugging becomes a pain too as it's harder to work out exactly which pieces of code are involved in a particular problem.
What I do this is to sketch out which parts of the app actually need which pieces of information, and pass those into the ViewControllers as they are created.