iOS custom UIView access properties in code - ios

So I've created a custom UIView subclass and have it assigned to a UIView in my main storyboard. When the view loads everything is displayed properly.
The issue I'm having is that I need to be able to access properties of said custom UIView since the view is data driven.
JSON_table.h:
#import <UIKit/UIKit.h>
#interface JSON_table : UIView
#property (strong, nonatomic) IBOutlet UIView *view;
#property (weak, nonatomic) IBOutlet UISearchBar *searchbar;
#property (weak, nonatomic) IBOutlet UITableView *table_view;
#property (weak, nonatomic) NSString *data_header;
#property (weak, nonatomic) NSString *data_list;
#end
JSON_table.m:
#import "JSON_table.h"
#implementation JSON_table
- (id) initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"JSON_table" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
#end
(I know I'm missing delegates for tableview, ill be adding these later)
The issue I'm having is when I right click on my UIView on my storyboard I get:
The problem is when I try to connect "view" to my header file "
ViewController.h" it doesn't let me create a IBOutlet, so I cannot reference my view and its properties in code.
This is what I am trying to accomplish:
"Table" is of type UIView
Idea:
Would this have anything to do with the UIView being on the second view in my storyboard? I noticed that I don't seem to have any problem attaching to anything on the first page, but the second one I can't.

You can only connect the outlets of a view to it's class object. You are trying to connect outlets of JSON_table object to UIViewController object.
If you need to access those properties in UIViewController object. You need to import
JSON_table.h
in your view controller. And create and instantiate a object of it.
JSON_table * customView = [[JSON_table alloc]init];
Now you can access all the properties of it as:
customView.searchbar, customView.view etc.
Added by theshadow124:
Thanks to everyone who attempted to help me solve my problem. Due to being fairly new to coding for iOS I didn't realize I had to assign a custom class to every UIViewController in my storyboard(I thought they they would inherit from the base if I didn't specify). simply creating a new subclass of UIViewController and assigning it under the Identity inspector fixed my problem and now I can properly assign outlets.
Im going to accept this answer because it was one of the issues I ran into after fixing the subclass on the storyboard issue.

Please make sure that in assistant editor your are opening the same class that your custom class is contained in .

Related

UIView custom xib doesn't show up

I'm having a problem that doesn't seem to have an obvious solution. I've searched around and I've been through all common answers that I could find.
My custom xib views don't show up on the app when I launch. The background is clear, and this xib has 5 image views as you can see below which aren't set to hidden.
The class has about 5 delegates as well which I set from a caller when the delegates have been initialized. The caller of initWithDelegates: is the parent UIViewController that displays this xib.
CustomView.h
#interface CustomView : UIView<SomeProtocol>
// UI Items - THESE AREN'T SHOWING UP
#property (strong, nonatomic) IBOutlet UIImageView *image1;
#property (strong, nonatomic) IBOutlet UIImageView *image2;
#property (strong, nonatomic) IBOutlet UIImageView *image3;
#property (strong, nonatomic) IBOutlet UIImageView *image4;
#property (strong, nonatomic) IBOutlet UILabel *label;
#property (strong, nonatomic) IBOutlet UIStackView *centerStackView;
- (id)initWithDelegates:(UIViewController*)delegate1 withDelegate2:(NSObject<Delegate2>*)delegate2 withDelegate3:(NSObject<Delegate3>*)delegate3 withDelegate4:(UIViewController<Delegate4>*)delegate4
withDelegate5:(NSObject<Delegate5>*)delegate5;
#end
CustomView.m
#implementation CustomView
- (void)awakeFromNib {
[super awakeFromNib];
}
- (id)initWithDelegates:(UIViewController*)delegate1 withDelegate2:(NSObject<Delegate2>*)delegate2 withDelegate3:(NSObject<Delegate3>*)delegate3 withDelegate4:(UIViewController<Delegate4>*)delegate4
withDelegate5:(NSObject<Delegate5>*)delegate5
{
NSArray * arr =[[NSBundle mainBundle] loadNibNamed:#"CustomView" owner:nil options:nil];
self = [arr firstObject];
self.delegate1 = delegate1;
self.delegate2 = delegate2;
self.delegate3 = delegate3;
self.delegate4 = delegate4;
self.delegate5 = delegate5;
[self setLoopImage];
[self layoutIfNeeded];
return self;
}
#end
What else I've verified:
I made sure that the xib file is properly selected under "Custom Class" in the interface builder.
I've walked through the code to make sure there are no crashes or obvious issues.
The xib doesn't appear to have any obvious issues in interface builder such as being set to HIDDEN.
The 5 IBOutlet ImageViews get a memory address and aren't nil.
Any help is appreciated!
UPDATE:
I believe this has something to do with putting the nibs in a nested UIView. In the interface builder, the order is UIViewController -> UIView -> nibs
There doesn't seem to be a method to register nibs from the parent UIViewController as there are in classes like UITableView.
I've also tried:
Setting the background color in the xib to make sure it shows up. It doesn't. However if I set the background color to red in the parent where I added the view in interface builder, it turns red. (See Figure 1), and my xib file is shown in Figure 2
Over-rode initWithFrame to make sure its being called. It is called.
Thinking that the view may be instantiated twice, one via autolayout and one via my custom init method, I tried making the (id)initWithDelegates method not init or register the nib in case that was duplicating the object. I did this by removing 1) return self, 2) the lines that register the nib, and 3) making the method prototype return void - I.E. (void)initWithDelegates - This didn't work either.
I tried these lines within initWithDelegates :
[self addSubview: self.image1];
[self bringSubviewToFront: self.image1];
[self.menuImage setHidden:image1];
-- with no luck.
Figure 1: (Actual result)
Figure 2 (Expected.. with red background)
Check your Autolayout in your custom XIB. Something the contain does not show because of it. For example: only center vertically & center horizontally. Try to do different autolayout constraint in your view in custom class.
I think something is wrong with layout of your CustomView inside ParentView. Could you please:
Check the frame of CustomView when you add it into the ParentView.
Check constraints that has CustomView inside ParentView. If you don't
have them - add it, constraints will iOS the glue how to layout your
CustomView. More information about this you can find here Programmatically Creating Constraints
And also you can try to use "Debug View Hierarchy" in Xcode to
inspect what is going on on your screen, there you can find your
CustomView in the view hierarchy and you will see what is wrong.
nibs cannot be nested within the structure.
Instead of:
UIViewController -> UIView -> nibs..
It should be:
UIViewController -> Container View -> UIView with nibs.

Cannot talk to elements inside xib

I am still learning interface builder.
I created a xib containing a button, a progress bar and a spinner. Lets call this xib MyToolbar.xib. I created classes for that xib (MyToolbar.h and .m). Inside the xib, I set the toolbar’s class to MyToolbar. Inside the xib I set File’s Owner to MyToolbar. I connected outlets to all elements and put them on the header.
The class header is this:
#import <UIKit/UIKit.h>
#interface MyToolbar : UIToolbar
#property (weak, nonatomic) IBOutlet UIButton *button;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
#property (weak, nonatomic) IBOutlet UIProgressView *progressBar;
#end
this is the implementation
#import “MyToolbar.h"
#implementation MyToolbar
- (id)init {
self = [super init];
if (self) {
self = [[[NSBundle mainBundle] loadNibNamed:#"MyToolbar"
owner:self
options:nil]
objectAtIndex:0];
}
return self;
}
Now I create the object on the main class
MyToolbar *toolbar = [[MyToolbar alloc] init];
at this point, toolbar is not nil but toolbar.button, toolbar.progessBar and toolbar.spinner are all nil.
I know the elements are not instantiated unless you display them.
Is there a way to make this work without displaying the object?
Did you connect the views to File's owner outlet? Try to remove the File's owner or connections and connect the views to MyToolbar.h outlets. I tried and it's working.

how to connect IBOutlet from a class to another class

I have Class A which contains a xib with some buttons and a UITextField and Class B which contains a tableView
I want to add Class A to the table view header.
I am importing the xib from class A into class B using [[[NSBundle mainBundle] loadNibName: owner:self options:nil] objectAtIndex:0];
I just want to reflect the button and textview actions inside classB. In ClassB I do have some UITextfield Delegate methods which i expect to be called when typing some text in uitextfield defined and declared in ClassA (xib + property definition in .h file).
Class A .h:
//properties are set from xib file ClassA.xib
#interface ClassA : UIView
#property (unsafe_unretained, nonatomic) IBOutlet UIButton *addC;
#property(strong, nonatomic) IBOutlet UITextField *nText;
#end
Class B.h
#import "ClassA"
#interface ClassB : UIViewController <UITextFieldDelegate, UITableViewDataSource,...>
#property (strong, nonatomic) IBOutlet UITableView *mTableView; //property set from ClassB.xib
#property(strong, nonatomic) IBOutlet UITextField *nText_B;
#property (unsafe_unretained, nonatomic) IBOutlet UIButton *addC_B;
- (IBAction)addC:(UIButton *)sender;
#end
I don't know how to make the link ClassB button and textfield to ClassA
In ClassB viewDidLoad method i;ve tried this:
getHeader = [[ClassA alloc]init];
_addC_B = [getHeader addC];
_nText_B = [getHeader nText];
_nText_B.delegate =self;
_nText_B.text=#"";
but it's not working
I am new to iOS on this side area.
Thank you for your help
You haven't explained your problem well. Classes do not "contain xibs".
If your objective is to create a piece of user interface in XIB and reuse it, you can achieve this with [NSBundle loadNibNamed:owner:options:]. The best way to reference parts of it is through properties like Noval explained in his answer. Another possibility is to attach views to "File's Owner" outlet's properties.
you can't connecting IBOutlet that placed outside your XIB class. but if you just want to access the outlet from other class, it's possible by creating instance of ClassA in ClassB. and then accessing the property like instanceOfClassA.outletObject

UITableView delegates not recognised after switching from UITableViewController to a UIViewController with separate UITableView

My problem is that until now I used a ViewController and inside this I create the UITableView programatically. For this ViewController I have created a class named WalkTroughViewController and set it inside Custom Class inside Identity Inspector.
Now I have changed, and I create another ViewController(deleted the old one) and drag a TableView from the Object Library. Then I have set the Custom Class of this new ViewController to WalkTroughViewController, but now when I run the project my UITableView delegates are not called.
I have also dragged a UITableViewCell inside the UITableView and set it to my custom cell class.
Any pointers what I have done wrong ?
edit:
#interface WalktroughScreenViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
- (IBAction)nextScreen;
#property (weak, nonatomic) IBOutlet UIButton *button;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
You can drag and assign the delegate and the dataSource of the table in the story board to the fileOwner (Your Controller)
or simply assign it programatically in ViewDidLoad method
self.tableView.delegate = self;
self.tableView.dataSource = self;
Did you assigned the delegate and the dataSource?
did you define
#interface YourClass: UIViewController <UITableViewDelegate, UITableViewDataSource>
Copy paste the code of your header so we can provide more help and see what's the issue

Changing outlet object properties

I have a view controller alertForNeedsClassification as a property in another class, as such:
#interface SCAAppDelegate()
{
HomeScreenViewController * _homeScreenViewController;
NSInteger SCAStatus;
}
#property (strong, nonatomic) PromptClassifyViewController * alertForNeedsClassification;
#end
#implementation SCAAppDelegate
#synthesize alertForNeedsClassification;
#synthesize window = _window;
PromptClassifyViewController's interface looks like this:
#interface PromptClassifyViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *headerTitle;
#property (weak, nonatomic) IBOutlet UITextView *message;
#property (weak, nonatomic) IBOutlet UIButton *notNowButton;
#property (weak, nonatomic) IBOutlet UIButton *classifyButton;
#property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
#property (weak, nonatomic) IBOutlet UIView *alertView;
#property NSUInteger tag;
#property (weak, nonatomic) IBOutlet id<PromptClassifyViewControllerDelegate> delegate;
- (void)show;
- (void)showFromView:(UIView *)view;
- (IBAction)show:(id)sender;
- (IBAction)dismiss:(id)sender;
- (IBAction)buttonWasPressed:(id)sender;
- (void)setHeaderTitleWithText:(NSString *)text;
#end
I am trying to change the values of IBOutlets message and headerTitle text, like this:
alertForNeedsClassification = [[PromptClassifyViewController alloc] initWithNibName:#"PromptClassifyViewController" bundle:nil];
//[alertForNeedsClassification setDelegate:self];
self.alertForNeedsClassification.headerTitle.text = #"A title";
alertForNeedsClassification.message.text = #"A message";
Then I show alertForNeedsClassification calling a show method (it's like a custom uialertview, but it doesn't subclass from uialertview).
Thing is, no matter how I change it, the text on alertForNeedsClassification.view is always that which is defined in the nib, ie. I can't change it programmatically.
My custom alert view is based on Jeff LaMarche's design: http://iphonedevelopment.blogspot.com/2010/05/custom-alert-views.html
Any ideas what might be going on?
Please be careful when you allocate and initialize the UIView object, especially if you trying to mix using Nib and dynamically generating objects. The best place is within -(void)awakeFromNib or -(void)viewDidLoad
Also, make sure these methods are called. By using -(id)initWithNibName:bundle: only cannot make sure your view to be loaded. Try -(void)addChildViewController and -(void)addSubview: on parentViewController's view to make sure view is loaded after being initialized.
If the text had to be prepared before being loaded, assign it to separate NSString property within PromptClassifyViewController class. Since this property is independent from view being loaded, you can change it's value BEFORE view is appeared. Make sure this text is used and applied to the headerTitle within -(void)show method.
Since you allocate PromptClassifyViewController and access weak referenced headerTitle from self. alertForNeedsClassification, make sure it's not deallocated right afterward.
Usually, weak option is not used for IBOutlet properties. Though it is used when generating outlet connection code by dragging objects from Interface Builder. Try testing your code using strong.
I was assigning values to the IBOutlets before they were alloc'd/initialized. The solution I implemented was to set the values I needed to non-IBOutlet properties (NSStrings in this case) and assign those where needed, in Prompt...Controller's viewDidLoad;

Resources