0

I am trying to get the class name of a UIViewController through one of its UI elements. When called in the following manner, the class method returns the correct name (eg: myViewController):

NSLog(@"Class name: %@", NSStringFromClass(self.class));

But when called like this, it only returns UIView:

UIButton *button = [[UIButton alloc] init];
[self.view addSubview:button];
NSLog(@"Class name: %@", NSStringFromClass(button.superview.class));

If I have reference to the button object, in another class for example, how could I get the actual name of its parent class?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
iSofia
  • 1,412
  • 2
  • 19
  • 36

1 Answers1

1

It violates the MVC design pattern for a view to directly access the view controller it's contained it. If you want the view to communicate with its view controller, this should be done through the delegate pattern:

First create a protocol that your view controller can implement:

@protocol ViewDelegate<NSObject>
- (void)viewDidDoSomething;
@end

@interface MyViewController<ViewDelegate>

@end

@implementation MyViewController
- (void)viewDidDoSomething {
    // React to the view doing something
}

Then create a custom view that is responsible for holding your UI and communicating with the view controller through its delegate:

@interface CustomView : UIView
@property (nonatomic, weak) id<ViewDelegate> delegate;
@end
Remover
  • 1,616
  • 1
  • 17
  • 27
Dash
  • 17,188
  • 6
  • 48
  • 49
  • Is there no way to just get name of the UIViewController? I'm trying to implement a dynamic UI creator, and the class that instantiates all the UI elements also handles all the events. Then, only selected events are relayed back to the parent through notifications. However, to keep track of all the elements, I've used a dictionary, which would also require the name of the parent class, which is used to create the notification name. All I need is the parent class name. Alternatively, is there any property in UIView or UIControl that could be used to store a custom string, perhaps? – iSofia May 30 '15 at 18:28
  • What is your dictionary currently mapping to and from? You could use a dictionary to hold the relationships between the `UIView` objects and the view controllers that they are displayed in. Add new views to your manager class with a method like `- (void)addNewView:(UIView*)view forViewController:(UIViewController *)viewController` – Dash May 30 '15 at 20:08
  • The class that handles the events should be the one to relate the views to view controllers. It doesn't make sense for the views themselves to know about their controllers. – Dash May 30 '15 at 20:09
  • Yes; a single class handles all the UI creation and methods, and a single global dictionary stores the type, tag, and metrics of each and every control it creates. The metrics are exclusively for picker views, since their delegate methods require the number of rows, components and their widths, and also their source data. _(continued...)_ – iSofia May 31 '15 at 07:59
  • The snag is with the event methods. For example, for `[button addTarget:uiController action:@selector(buttonHandler:) forControlEvents:UIControlEventTouchDown];` the method, _buttonHandler_, would only provide the sender, in this case the button object, and not the view controller that it belongs to. _(continued...)_ – iSofia May 31 '15 at 08:00
  • However, my notification system generates specific _notification names_ for each view controller when dispatching the event messages. For example, in `[uiEvent postNotificationName:@"eventFor_myViewController" object:uiController userInfo:uiEventData];` the _notification name_ was a generated string, concatenating _eventFor_ with the name of the intended view controller; _that view controller would be the exclusive observer for that message_. This message targeting would allow same tag numbers to be used across separate view controllers. – iSofia May 31 '15 at 08:02
  • The tag numbers are invariably reused across view controllers as they are enumerated constants, like this: `enum { nameText = 1, dateSelector, nameButton, clearButton, submitButton };` – iSofia May 31 '15 at 08:09
  • This is a perfect use case for delegates. Whichever class receives the buttonHandler: selector should have a delegate that points to whichever view controller needs to receive that message. – Dash May 31 '15 at 21:48
  • I see what you mean; since the UI controller would be communicating "exclusively" with the class that instantiated it through its delegate methods, it wouldn't be necessary to identify it, as would be the case with notifications. Thank you for taking the time to explain it to me. – iSofia Jun 01 '15 at 07:50