My top level UIView
contains a some labels and a drawing canvas. The drawing canvas is itself a UIView
which overrides its drawRect()
method and, of course, the various touch methods. When the user has finished drawing, I want to update one or more labels that are outside the canvas (i.e. are all components of the top level UIView
).
What's the best way to do it?
I currently have the top level UIViewController
pass the various labels into my CanvasView
s from the top level viewDidLoad()
method and I store them locally. Whenever I need to update a label, I do so from the local copies of these sibling views I have - But I'm not happy with this because it feels kludgy.
To explain further, this is what I do in my top level UIViewController
:
@IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for v in self.view.subviews {
if v .isKindOfClass(CanvasView) {
let canvasView = v as CanvasView
canvasView.setMyLabel(myLabel)
}
}
}
And then in my CanvasView.swift
file, I have:
private var myLabel: UILabel!
...
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
// do stuff ...
setNeedsDisplay()
myLabel.text = "etc.etc."
}
Is there a better way?
Thanks.
Ave
If your canvas is a separate viewController
, you can use delegate protocols to access your base view controller from the canvas view controller.
Suppose you have a BaseViewController
which calls the canvasViewController
.
In your canvasViewController.h
add the following :
@protocol CanvasDelegate <NSObject>
@required
//examples . add your methods to upgate labels here
- (void) updateLabels: (NSString*) labelText1 and:(NSString*)labelText2;
@end
@interface canvasViewController : UIViewController
{
id<CanvasDelegate> delegate;
}
@property (retain) id delegate;
@end
Now from your canvasViewController.m
file execute this code whenever you want to update your labels (or ask the baseViewController to do something) :
[[self delegate] updateLabels:string1 and:string2];
Now for your base view controller to accept messages from the canvas, the BaseVC has to "adopt" the CanvasDelegate
Protocol and also implement the required methods.
In baseViewController.h
, add the following :
@interface baseViewController : UIViewController <CanvasDelegate>
In baseViewController.m
when you create an object of canvasViewController for pushing, add the following command :
canvasVC.delegate = self;
And don't forget to implement the required methods in baseViewController.m
like so :
- (void) updateLabels: (NSString*) labelText1 and:(NSString*)labelText2
{
//update your labels here
}
I would implement the delegate pattern. When creating the canvas pass the parent viewcontroller where you can implement various callback methods.
Here you can find a more detailed explanation of the various methods of implementing a delegate. Some of them might be overkill for this single and simple usecase.
Example: you have a game insance (called game), which defines a delegate protocol. the protocol contains several methods for different events. (e.g. -(void)gameDidFinish
etc.)
Now the game implements a method addDelegate
which is called by every instance, which wants to be notified for certain events of the game. All of these instances, who register themselves as delegates implement all or some of the methods defined in the games protocol
If one of the game events is triggered the game checks all of its registered delegates if they have implemented the corresponding method and calls it.
Important: as mentioned the protocol ma be overkill, as you have only one delegate.