I have an app which uses maps on several different screens. All the maps should display the same basic information (annotations and overlays), but every instance adds different additional annotations and overlays to the map. I want to create a class, which implements the common features and behaves exactly like the MKMapView. How is this possible?
I've had three ideas to solve this, but none of them seems to be a good solution.
Subclass MKMapView. The problem with this approach is that the map gets the information about it's annotations and overlays from it's delegate, which should be the subclass (a view...) itself, therefore adding additional data is problematic (I can't set the delegate other than the class itself).
Wrap MKMapView. I could create an NSObject/UIView subclass which has an MKMapView, but either I have to proxy all of the map's methods to my class or access the map with a knowledge of the inner objects (myMapView.mapView.xxx...).
Create a delegate class (NSObject with MKMapViewDelegate functions). The delegate class could then implement the common behavior. This solution also has issues similar to the first one.
How can I solve this elegantly?
Create a class and Add Map to view of that class.
Now make that class as parent class for all class where you want to add Mapview.
Provide data to parent class when you want to add annotations and overlays.
Related
I am wanting to create a base class that inherits from CCLayer. My reason is because I have a single-image, full screen CCSprite that I want to overlay on every scene of my application. Creating a base class, and adding a CCSprite containing the image as the top-most Z object seems to make sense because it will prevent me from having to re-code the same overlay implementation again and again for each scene.
I've been able to derive a class from CCLayer with relative ease. However, I cannot figure out how to correctly create a scene another layer class that is a child, of a child of CCLayer. How can this be done, and work?
I understand that when most users ask such questions, the first follow is "Show us your code." I can show you the code but I am most interested in is a very generic implementation of Cocos2d object, that is derived from CClayer and can be used as a base class for other layers, pre-wiring common sprites and objects.
I think this may be your problem:
"I cannot figure out how to create a scene that is a child, of a child of CCLayer."
As I understand it, Cocos layers are added as children to Cocos scenes, not the other way around, as the quote seems to imply.
I think you could simply make a custom layer class, deriving it from CCLayer and adding your CCSprite. Then simply go to everywhere you are creating or deriving a CCLayer and instead create or derive it from your custom layer class and then show or hide the sprite when needed.
Alternatively, and probably more easily, you could create a category on CCLayer adding a "showFullscreenSprite" method which simply creates the sprite and sets its image, then calls
[self addChild:yourSprite z:yourSprite.zOrder tag:9999];
You would also need a corresponding "hideFullscreenSprite" method which would simply do this
[self removeChildByTag:9999 cleanup:YES];
The nice thing about this approach is you wouldn't need to sub-class at all and all of your CCLayers would now have your "showFullscreenSprite" and "hideFullscreenSprite" methods available.
(Note: "9999" has to be some number you're not already using as a CCNode tag. Make it big enough so you don't have to worry about it. Maybe pull it out into a constant such as "FULL_SCREEN_SPRITE_TAG" or some such for readability.)
Hope this helps!
I have a custom UIView class which needs to know about its parent (another different custom UIView class).
The parent class has to import the header of the child class, so it can add subviews of that class.
The child class has to import the header of the parent class, so it can access its methods and properties. It has to do the import in its .h file rather than its .m, because I need to make the child's parent an instance variable.
If I do this, I get circular import issues.
If anyone can make any sense of this, can you help to resolve this? Thanks.
What you want is commonly known as a forward declaration.
refer to Objective-C: Forward Class Declaration for more information
There are many ways to solve this, for example by just declaring the reference to the other class as an id, and to send forward messages to it (in Objective-C you don't even need to cast them, the compiler wouldn't complain about that).
For example:
#property(nonatomic,weak) id child;
But you may review your design in a way that you use a root controller that handles both the classes. This way A doesn't directly speak to B and B doesn't directly speak to A. Instead if A wants to speak with B, speaks with C and C speaks with B, and viceversa.
While you could use a forward declaration (#class ParentClass) and a weak reference to the parent (#property (nonatomic, weak) ParentClass *parent) in the child's header file, this is generally not a good programming practice.
Reasons why this is generally not a good idea:
1) As the project gets bigger, you're likely going to violate DRY ("don't repeat yourself") as the child necessitates a parent of a certain class... what if another parent later needs to create the same child object? You'd have to create a new class that declares another forward class of the new parent and has a weak property to it.
2) This is also likely going to lead to spaghetti code... what if you want to add a new feature to the parent that affects a method the child is using? Do you create a new yet similar method that's slightly different (see point 1 about violating DRY)? Do you create an input to the original method (you'd also have to make sure that the child now knows about this change and passes the appropriate input).
Instead, the Delegation design pattern works better here. Apple also frequently uses this throughout their libraries. In example, UITableView declares a delegate and a datasource so that it can delegate actions (clicks on cells) and data input (creation of custom cells) to other owning classes, without the UITableView object having to know about the implementation of said parent class.
For more information on the Delegation pattern in general, see Wikipedia on it here:
http://en.wikipedia.org/wiki/Delegation_pattern
For a tutorial on creating your own protocols (how delegation is implemented in iOS), see this tutorial here:
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-custom-delegates/
For high quality tutorials and introductions on iOS in general, including delegation and other necessary iOS concepts, see Ray Wenderlich's site also here:
http://www.raywenderlich.com/
Good luck!
I know it's possible to attach a custom view controller class to several different view controllers on a storyboard, but can it be done in the other direction; that is, depending on the situation, I want to bind different custom classes to a single view controller on the storyboard that will be instantiated using:
[self.storyboard instantiateViewControllerWithIdentifier:]
background: I used to have several view controllers on my storyboard that are almost identical. In fact, the custom classes that they each bind to are very similar as well. In an effort to clean this up, I refactored my custom classes into one base class and several subclasses. I then removed all the similar view controllers from the storyboard leaving only one which I've bounded to my base class. I then call:
MySubclass* mySubclass = [self.storyboard instantiateViewControllerWithIdentifier:#"StoryboardControllerBoundToBaseClass"];
Unfortunately, my subclass code is being ignored and only the base class code is ever run. Does anyone know how I can make it work without duplicating view controllers on the storyboard and binding each one to a different subclass?
It's not possible. Just because you say MySubclass *object = something doesn't magically convert object into a MySubclass object. It's stored in the storyboard with whatever class was assigned at storyboard compile time.
Rather than using subclassing, I figure I can reuse a view controller on the storyboard by using a delegate/proxy model. More specifically, I can bind the storyboard's view controller to a custom class that delegates all of its methods/events to others classes to handle. This isn't as elegant as subclassing but at least I can keep my storyboard leaner, not having to keep several copies of pretty much the same view controller. Plus, I won't need to duplicate future changes to every copy of these controllers to boot.
As guylegend writes. Apple doesn't support the way to do that. There are many workarounds e.g. with delegates but I finally found the answer and answered in another topic. Hope it helps!
https://stackoverflow.com/a/32103618/1943053
In my iphone application, I have multiple view classes and model class and I take the property of view class to my model class via setter but I do not use in other view class this instance via getter. For instance, in viewA class I have text Field instance and in modelA class I have Nsstring object to hold textField instance, and I use the instance of ModelA in viewA and I take the textField instance to ModelA class via Setter, but in ViewB class I have instance of ModelA but I do not take this object via getter, How can I handle this problem?
p.s.I started to programming a little time ago, I am new in objective c programming..
Its really hard to understand the specifics of your question, perhaps an example will be useful here. However, if your purpose is to share data between views you create a Data Model class in code before the views are created (maybe in the app delegate) and pass it to both view classes on creation. They can both hold a reference to the same object.
Here is a simple tutorial I wrote a while back which shows the use of multiple views in a tab bar. It passes the text from one view to the other. There is source code in the tutorial as well. The code design is not the best I have ever made but I was trying to keep it simple.
iPhone Tab Bar tutorial
In my program, I have a class called Object, which inherits from UIView. I also have other objects called: circle, square, triangle which inherit from Object.
My problem is that I would like to make a possible object called Image, which also inherits from Object. I would like all objects on the screen to inherit from Object, and then pass an NSArray pointer to my physics functions that contains all objects on the screen.
What is the best way to have my Image object acquire all the properties of my Object class?
Should I just create new properties for my Image object, or is there a way to inherit Object and still be able to display an image, since Object inherits from UIView and not UIImageView.
You've realized that a class cannot extend two parent classes.
Could your "Object" be a Protocol instead of a Class? That way circle, square and image could all implement that protocol while extending either UIView or UIImageView as needed?
That's a very…unusual way to do it. Have you had any Java experience?
What are you trying to do with the Shapes? Are you trying to draw them in those respective classes? Here, you're blurring the lines of MVC. From what it seems like, your Circle, Square, etc. classes are both a model and a view, which shouldn't happen. If you're trying to draw the shapes, you wouldn't create classes for them—you'd use the Quartz drawing methods to draw them in your view controller's view. If you're trying to store info about those shapes, you wouldn't want them to inherit from UIView. NSObject (or a custom Shape class) would be a better option. (It's also a bad idea to call the class "Object"—it could get confused with NSObject).
You're second paragraph is where my first question came from. Your NSArray does not have to contain variables of the same type—this is very different from Java's arrays (and other languages such as C# and C). Therefore, unless there were some methods or ivars you wanted to inherit, there was no reason to declare the Object class.
As for displaying images, what are you intending to do with Image? If you just want to display images (a view), then make it a subclass of UIImageView (which is a subclass of UIView). If you want do store information about images, make it a subclass of Shape (or in this case, your Object). However, you really can't do what you want to (inherit from both Object and UIImageView) because you shouldn't combine functionality of views and models.
Really, your best option here is to revisit your classes, make them adhere to MVC, and rethink your inheritance chain. Hope this helps!
The simplest thing would be to have Image inherit from Object and then have Image own a subview of type UIImageView.