Reusing code-based UIView versus XIB

Let's say that I have a UIView that I would like to reuse in several view controllers, given that this is a pretty general UIView object with a high reuse value (like a UITextField or UISegmentedControl ). In my opinion, it would be much easier to reuse this UIView if I wrote a UIView in the code, instead of doing XIB using Interface Builder. I came to this conclusion, because if the UIView is written in code, I can simply initialize a new instance of this UIView in any controller of the form:

 MyGreatReusableView *greatReusableView = [[MyGreatReusableView alloc] initWithFrame:CGRectMake(...)]; 

... and then directly access the properties and attributes of this UIView, as well as with UIView controls such as UITextField with its properties .text , .textColor , etc.

However, if I create a UIView as an XIB, it must be bound (via a File Owner or IBOutlet in the View object in the XIB) to a specific view controller and therefore can only be used in that view controller. In addition, I can only access the properties of controls on the XIB using IBOutlets that are connected to this view controller.

I think I completely misunderstood something regarding XIB files, as this is apparently very limited! If someone can provide clarification regarding the possibility of reusing XIB files in several view controllers and, if so, provide an example of a code-based solution and an XIB-based solution, I would be very grateful.

Thanks in advance for your help!

+4
source share
2 answers

Indeed, you can use the same view in multiple controllers. You were on the right track. The key is that you do not need to use the view controller to which the view is attached. Here's what I do for reusable table cells (which contain things like sliders)

  • Create a new XIB file
  • Create a new view (in my case it was a table cell)
  • Set UIViewController.view as a view (again, a table cell)
  • I connect it to this code (currently used in production):
     @implementation TableCellFactory +(UITableViewCell*) createCellInstanceFromXIBName:(NSString*)name { UIViewController* tmp = [[UIViewController alloc] initWithNibName:name bundle:nil]; UITableViewCell* cell = (UITableViewCell*)[tmp view]; DebugAssert([[cell class] isSubclassOfClass:[UITableViewCell class]], @"XIB view cell is not a subclass of UITableViewCell; xib name:%@",name); DebugAssert(cell != nil,@"cell is nil -- Xib name:%@",name); [cell retain]; [tmp release]; return cell; } @end
    @implementation TableCellFactory +(UITableViewCell*) createCellInstanceFromXIBName:(NSString*)name { UIViewController* tmp = [[UIViewController alloc] initWithNibName:name bundle:nil]; UITableViewCell* cell = (UITableViewCell*)[tmp view]; DebugAssert([[cell class] isSubclassOfClass:[UITableViewCell class]], @"XIB view cell is not a subclass of UITableViewCell; xib name:%@",name); DebugAssert(cell != nil,@"cell is nil -- Xib name:%@",name); [cell retain]; [tmp release]; return cell; } @end 
+1
source

An alternative solution, without having to set IBOutlets in a reusable view, would be to assign the lookouts you want to use with a specific tag. Then you can get the submission with the tag.

For example, if you want to create a view with a label and a text field. The process for this:

  • Create empty xib
  • Set the view with a label and text box as a subheading.
  • Assign a label and text field with different tags (let them say 10 and 11)

  • Create a header file for this xib and define macros for the tags
    #define kReusableViewNibName @"ReusableViewNibName"
    #define kLabelTag 10
    #define kTextFieldTag 11

  • Now you can load xib in any view controller you want:

 // Import header file with previous defines NSArray *rootViewsFromXib = [[NSBundle mainBundle] loadNibNamed:@"NameOfXib" owner:nil options:nil]; // There is only one root view in the xib, // the view that contains the label and text field UIView *loadedView = [rootViewsFromXib objectAtIndex:0]; // You can now use the views from within the xib // by using the tags to obtain the views. UILabel *label = (UILabel *)[loadedView viewWithTag:kLabelTag]; UITextField *textField = (UITextField *)[loadedView viewWithTag:kTextFieldTag]; 
+2
source

Source: https://habr.com/ru/post/1338542/


All Articles