MVC iOS breakout game design - model-view-controller

I have the following models in my breakout like game:
Ball.h
Block.m
GamePlay.m
Paddle.h
Paddle.m
I also have the following views:
BallView
BlockVIew
PaddleView
My question is, when I change a property in the model, I have to change the property in the view also. For example:
Ball Model:
#interface Ball : NSObject
#property (nonatomic, strong) NSNumber *radius;
#property (nonatomic, strong) NSNumber *xSpeed;
#property (nonatomic, strong) NSNumber *ySpeed;
#property (nonatomic, strong) NSNumber *xDirection;
#property (nonatomic, strong) NSNumber *yDirection;
#property (nonatomic) CGPoint location;
#property (nonatomic, strong) UIColor *color;
#end
Ball View:
#interface BallView : UIView
#property (strong, nonatomic) UIColor *color;
#property (nonatomic) int radius;
#end
When the model has its properties changed, I have such as location, or color. I have to update these same properties in the view. Should I NOT track location and color in my model?

I think the main point in MVC is maintainability over time. If you decide you need an entirely different view of your game tomorrow, the model code can stay the same, so you can focus on modifying just the view part.
Also, if you know you need some data about the game's state, you know where you can find it - in the model. For example, you might want to transmit the ball's location over the internet to your friend, if he is interested in watching you breaking blocks.
As you can probably guess from the last two paragraphs, you should indeed store and update the location and color of the ball in the model. The view shouldn't be the owner of app state.

Related

many-to-one relation core data

I am obviously new in Core Data, I have read quite a lot about the topic from Apple and from countless other sources. However, none seems to treat the many-to-one relation in a way for a newbie like me to understand. I seems to be fine with one-to-one relation, but I have some difficulties on understanding many-to-one relation.
My problem is as follow:
I am working on a small project to practice Core Data. In my project, there are two entities:Person and Note and they are related as follow:
(Sorry, couldn't add the picture)
A Person can have several notes, but Note can only have one owner, Person. Person entity is related with a one-to-many relation (double arrows pointing to the entity: Note), while the entity Note is related with a many-to-one (single arrow pointing to Person)
This is what I have so far:
Note.h
#class Person;
#interface Note : NSManagedObject
#property (nonatomic, retain) NSDate * noteCreateDate;
#property (nonatomic, retain) NSString * noteUser;
#property (nonatomic, retain) Person *person;
Person.h
#class Note, Organise;
#interface Person : NSManagedObject
#property (nonatomic, retain) NSString * personAddress;
#property (nonatomic, retain) NSData * personAvatar;
#property (nonatomic, retain) NSString * personBDay;
#property (nonatomic, retain) NSDate * personFutureDate;
#property (nonatomic, retain) NSString * personGender;
#property (nonatomic, retain) NSString * personName;
#property (nonatomic, retain) NSString * personRelation;
#property (nonatomic, retain) NSSet *notes;
#property (nonatomic, retain) NSSet *organises;
#end
#interface Person (CoreDataGeneratedAccessors)
- (void)addNotesObject:(Note *)value;
- (void)removeNotesObject:(Note *)value;
- (void)addNotes:(NSSet *)values;
- (void)removeNotes:(NSSet *)values
In my view controller I am trying to save the notes as follow:
NSManagedObjectContext *context = [self managedObjectContext];
Note *newNote;
newNote = (Note *) [NSEntityDescription insertNewObjectForEntityForName:#"Note" inManagedObjectContext:context];
// Saving the notes
newNote.noteUser = noteTextView.text;
newNote.noteCreateDate = added;
[newNote setPerson:newNote.person];
///////////////Saving to the DataBase /////////
NSError *error = nil;
if ([self.managedObjectContext hasChanges]) {
if (![self.managedObjectContext save:&error]) { //save failed
NSLog(#"Save Failed: %#", [error localizedDescription]);
}
else {
NSLog(#"Save Succeeded");
}
}
It is saving the data in the database fine, but the problem is: There is no relationship between Person and Notes in the database. The column for person in the database is empty (not showing to whom the note belong to).
I have tried several things to try to link the person with the note, NONE of them seems to work. So, it seems that I am stucked and I would very much appreciate some help.
This is the latest tutorial I used for help:
http://brandontreb.com/core-data-quicktip-inverse-relationships
https://itunes.apple.com/fr/itunes-u/advanced-iphone-development/id407243028?l=en&mt=10
Thank you.
Your code does not create any relationship between the Note and a Person. This:
[newNote setPerson:newNote.person];
is the same as newNote.person = newNote.person; and does not change anything.
You must create a Person object (or fetch an existing Person) and then set
newNote.person = thePerson;
to establish the relationship.

Declare a Mutable Dictionary (to use addEntriesFromDictionary) in header file

I need to use several times:
[mutableDict addEntriesFromDictionary:dictionary];
I don't know how to declare mutableDict in the header file. I try with:
#property (nonatomic, assign) NSMutableDictionary *mutableDict;
#property (nonatomic, retain) NSMutableDictionary *mutableDict;
#property (nonatomic, retain, readwrite) NSMutableDictionary *mutableDict;
And more...
How I must to declare this NSMutableDictionary??
In your header file use #property (nonatomic, retain) NSMutableDictionary *mutableDict; if your are not using ARC, or #property (nonatomic, strong) NSMutableDictionary *mutableDict; if you are using ARC.
In your implementation include #synthesize mutableDict; or better #synthesize mutableDict = _mutableDict; somewhere after #implementation YourClass.
You should also initialize it with something like _mutableDict = [[NSMutableDictionary alloc] init];
If you do not need your mutable dictionary used from outside (ex: [myobject.mutableDict addEntriesFromDictionary:dictionary]; you better not define it in your header file but in your implementation like:
#implementation YourClass {
NSMutableDictionary *_mutableDict;
}
and initialize it like shown above

Xcode - viewDidLoad method not working

I am new to Objective-c and Xcode, yet I believe I know enough about it to realize that something is going wrong here. I have an application using a storyboard, and one of the views in the application is not running its viewDidLoad method. I am not sure if this is relevant, but I had recently accidentally deleted my original storyboard, and had to make another one. The original had worked great with no problems, yet when I use the new one, it does not work. The view in question is also the first view of a Tab Bar Controller, which might be part of the problem.
Here is the code from the class responsible for the view (.h):
#import <UIKit/UIKit.h>
#interface TabSynth : UIViewController
#property (nonatomic, retain) IBOutlet UIImageView *tomeWater;
#property (nonatomic, retain) IBOutlet UIImageView *tomeFire;
#property (nonatomic, retain) IBOutlet UIImageView *tomeAir;
#property (nonatomic, retain) IBOutlet UIImageView *tomeEarth;
#property (nonatomic, retain) IBOutlet UIImageView *tomeDark;
#property (nonatomic, retain) IBOutlet UIImageView *tomeLight;
#property (nonatomic, retain) IBOutlet UIButton *airSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *darkSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *earthSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *fireSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *lightSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *waterSynthButton;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv1;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeWater1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeFire1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeAir1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeEarth1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeDark1;
#property (nonatomic, retain) IBOutlet UIImageView *tomeLight1;
And here is the code from the (.m):
#import "TabSynth.h"
#implementation TabSynth
#synthesize tomeWater;
#synthesize tomeFire;
#synthesize tomeAir;
#synthesize tomeEarth;
#synthesize tomeDark;
#synthesize tomeLight;
#synthesize tomeWater1;
#synthesize tomeFire1;
#synthesize tomeAir1;
#synthesize tomeEarth1;
#synthesize tomeDark1;
#synthesize tomeLight1;
#synthesize airSynthButton;
#synthesize darkSynthButton;
#synthesize earthSynthButton;
#synthesize fireSynthButton;
#synthesize lightSynthButton;
#synthesize waterSynthButton;
#synthesize synthButtonLarv;
#synthesize synthButtonAmoeb;
#synthesize synthButtonLarv1;
#synthesize synthButtonAmoeb1;
-(void)viewDidLoad {
extern int gTomeAir;
extern int gTomeDark;
extern int gTomeEarth;
extern int gTomeFire;
extern int gTomeLight;
extern int gTomeWater;
extern int gAmoebaeNum;
extern int gLarvaeNum;
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
if (gTomeAir>0) {
tomeAir.hidden=NO;
tomeAir1.hidden=YES;
airSynthButton.hidden=NO;
}
if (gTomeDark>0) {
tomeDark.hidden=NO;
tomeDark1.hidden=YES;
darkSynthButton.hidden=NO;
}
if (gTomeEarth>0) {
tomeEarth.hidden=NO;
tomeEarth1.hidden=YES;
earthSynthButton.hidden=NO;
}
if (gTomeFire>0) {
tomeFire.hidden=NO;
tomeFire1.hidden=YES;
fireSynthButton.hidden=NO;
}
if (gTomeLight>0) {
tomeLight.hidden=NO;
tomeLight1.hidden=YES;
lightSynthButton.hidden=NO;
}
if (gTomeWater>0) {
tomeWater.hidden=NO;
tomeWater1.hidden=YES;
waterSynthButton.hidden=NO;
}
if (gAmoebaeNum > 0) {
synthButtonAmoeb.hidden=NO;
synthButtonAmoeb1.hidden=YES;
}
else {
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
}
if (gLarvaeNum >= 1) {
synthButtonLarv.hidden=NO;
synthButtonLarv1.hidden=YES;
}
else {
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
}
}
In the if statements, the external integers being called (gTome) were set equal to a number in the previous view. Any help at all would be great, and I apologize for the simpleness of my coding.
If it's not calling viewDidLoad, then the first thing to check is that in your storyboard you have properly set TabSynth as the custom class of your view controller. Also, I don't see an NSLog in your viewDidLoad method. How do you know it's not being called?
By the way, did you know that you can put non-UI objects in a nib or storyboard? I think this might help you simplify your code. For example, you could have a class ElementViews defined like this:
ElementViews.h
#interface ElementViews : NSObject
#property (assign, nonatomic) IBOutlet UIImageView *tome;
#property (assign, nonatomic) IBOutlet UIButton *synthButton;
#property (assign, nonatomic) IBOutlet UIImageView *tome1;
#end
and then in your TabSynth class, instead of three outlets for every element, you just have one outlet:
TabSynth.h
#class ElementViews;
#interface TabSynth : UIViewController
#property (nonatomic, retain) IBOutlet ElementViews *waterViews;
#property (nonatomic, retain) IBOutlet ElementViews *fireViews;
#property (nonatomic, retain) IBOutlet ElementViews *airViews;
#property (nonatomic, retain) IBOutlet ElementViews *earthViews;
#property (nonatomic, retain) IBOutlet ElementViews *darkViews;
#property (nonatomic, retain) IBOutlet ElementViews *lightViews;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonLarv1;
#property (nonatomic, retain) IBOutlet UIButton *synthButtonAmoeb1;
...
In your storyboard, you drag a generic "Object" (looks like an orange cube) into your TabSynth scene. Change its custom class to ElementViews and its identity label to Water Views. Connect the waterViews outlet of the TabSynth to this new ElementViews object, and connect the outlets of the ElementViews object to the three water views (the tome and tome1 image views and the synthButton button). Repeat for the other five elements.
Then you can simplify your viewDidLoad method like this:
- (void)configureElementViews:(ElementViews *)elementViews state:(int)state {
if (state > 0) {
elementViews.tome.hidden = NO;
elementViews.tome1.hidden = YES;
elementViews.synthButton.hidden = NO;
}
}
- (void)viewDidLoad {
extern int gTomeAir;
extern int gTomeDark;
extern int gTomeEarth;
extern int gTomeFire;
extern int gTomeLight;
extern int gTomeWater;
extern int gAmoebaeNum;
extern int gLarvaeNum;
synthButtonAmoeb.hidden=YES;
synthButtonAmoeb1.hidden=NO;
synthButtonLarv.hidden=YES;
synthButtonLarv1.hidden=NO;
[self configureElementViews:self.waterViews state:gTomeWater];
[self configureElementViews:self.fireViews state:gTomeFire];
[self configureElementViews:self.airViews state:gTomeAir];
[self configureElementViews:self.earthViews state:gTomeEarth];
[self configureElementViews:self.darkViews state:gTomeDark];
[self configureElementViews:self.lightViews state:gTomeLight];
}
ok but you must write [super viewDidLoad] at the beginning of the method -viewDidLoad to call the viewDidLoad of the Controller itself (the father or its predecessor in the hierarchy of object) before writing your superb code which create a derived version of -viewDidLoad.
voila, good luck.

Trying to use KVC in Xcode to update a TextLabel

I've got a TextField that I'm trying to update the values as it progresses through running my code using KVC. Unfortunately I cannot seem to get anything to update past the initial value.
I've used the bindings on the button that launches the code, the TextField that I want to update and it just doesn't want to update. Please forgive me for the n00bish question but I've been searching online all day, going through tutorials, rewriting the code different ways and can't seem to figure out why this very simple tasks won't work.
Here is my KVC.h file:
#import <Foundation/Foundation.h>
#interface KVC : NSObject{
NSString *_progressString;
}
#property (nonatomic, retain) NSString *progressString;
#end
Here is my App header file:
#import <Cocoa/Cocoa.h>
#import "KVC.h"
//UI Controls
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *window;
NSPersistentStoreCoordinator *__persistentStoreCoordinator;
NSManagedObjectModel *__managedObjectModel;
NSManagedObjectContext *__managedObjectContext;
NSButton *_loadingExtracts;
NSButton *_processStuff;
NSProgressIndicator *_progressBar;
KVC *myProgressString;
}
#property (assign) IBOutlet NSWindow *window;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (assign) IBOutlet NSButton *loadingExtracts;
#property (assign) IBOutlet NSButton *processStuff;
#property (assign) IBOutlet NSProgressIndicator *progressBar;
- (IBAction)saveAction:(id)sender;
- (IBAction)loadingExtracts:(id)sender;
- (IBAction)processStuff:(id)sender;
#end
And finally, here is the function inside the code that I cannot get to update.
- (IBAction)processStuff:(id)sender
{
KVC *frickenHeck = [[KVC alloc] init];
NSLog(#"Button Pressed - Processing Information");
[myProgressString setValue:#"Testing" forKey:#"_progressString"];
[_progressBar setUsesThreadedAnimation:YES];
[_progressBar startAnimation:self];
//Turn off Progress Bar
[_progressBar stopAnimation:self];
[frickenHeck setValue:#"Completed" forKey:#"_progressString"];
//[_progressText setStringValue:#""];
}
(As you can see, I've tried updating 2 different ways and neither work. The allocation seems to set up the initial variable just fine, the Log shows I'm in the method, just can't get my label to update past the allocation).
Any thoughts or ideas would be greatly appreciated.
I am more of a iOS developer, so I am not 100% certain how some of the standards cross-over to the OSX side of things. Nevertheless,
You are saying that you are using KVC, like it is a framework providing a easy to use key-value coding scheme, which doesn't necessarily make sence. This appears to be a custom class you created called KVC.
In your KVC.m file did you #synthesize this variable?
#implementation KVC
#synthesize progressString = _progressString;
You have defined your object frickenHeck as class KVC which holds a property called progressString, that you are making available to other classes via this call.
#property (nonatomic, retain) NSString *progressString;
Assuming you have synthesized the variable in your #implementation file, why don't you just call:
frickenHeck.progressString = #"Testing";
or
frickenHeck.progressString = #"Completed";
Sure you can set the variable via Key Value Coding, but not by setting to the private form of your class variable. Try:
[frickenHeck setValue:#"Completed" forKey:#"progressString"];
So, have you synthesized this variable? Or at least set a accessor setter/getter for the variable? You typically only want to do one or the other.
Header:
- (void)progressString;
- (NSString *)setProgressString:(NSString *)_string;
Implementation:
- (void)progressString {
return _progressString;
}
- (NSString *)setProgressString:(NSString *)_string {
_progressString=_string;
}
Also to note that if you are going to be changing this variable a lot, you may want to use the NSMutableString form of the class, and set the #property declaration to copy. #property (nonatomic, copy) NSMutableString *progressString;
I hope some of this information assists you on your journey..
Mark

objective C: may not respond to (issue)

I have two UINavigationController in the appdelegate.h
{
UINavigationController *leftView;
UINavigationController *rightView;
UIWindow *window;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *leftView;
#property (nonatomic, retain) IBOutlet UINavigationController *rightView;
appdelegate.m
#synthesize leftView;
#synthesize rightView;
then in a different class
test.m
#import "appdelegate.h"
if I do:
[self leftView] pushViewController...; //(Everything is ok)
but if I change it to:
[self rightView] pushViewControll...; //it complains about ViewController may not respond to -rightView
You code seems right; what doesn't seem right is that you're including AppDelegate. If the code was in AppDelegate.m, it would probably work without any complaints by the compiler.
Instead, you've defined #property lines for each, but that is in AppDelegate.h, not test.h - but you're using them in test.m. That is probably the source of the problem.
Interestingly, does the code actually run?
I'm going to hazard a guess: Have you declared and synthesized a property for rightView, or at least provided your own manual getter?
It sounds like you declared a #property or method called leftView that returns the leftView ivar, but you forgot to do the same for rightView. The error is telling you that self doesn't respond to the selector rightView.

Resources