How to access member of a subclass of UIView - ios

I have a custom View
#interface Slip : UIView{
UIButton *number1;
}
#property (nonatomic, assign) IBOutlet UIButton *number1;
#end
with a nib file, the "Slip" is the fileĀ“s owner of the nib File.
I initialize the View in a ViewController like this:
self.slip1 = [[[NSBundle mainBundle]loadNibNamed:#"SlipNib" owner:self options:nil] objectAtIndex:0];
[self.slip1 setFrame:CGRectMake(0.0f, 0.0f, 307.0f, 322.0f)];
[self.slips addSubview:self.slip1];
now I want to access the member of the Slip
[self.slip1.number1 setSelected:YES];
this line throws an exception
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ViewController 0x755e9d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key number1.'
How can I access the member (number1). I have 12 of these views in my ViewController and need to access them seperately. Any help much appreciated.

It sounds like you haven't connected the IBOutlet to the button in Interface Builder. You should right click and drag from 'Files Owner' to the button and then select button1.
It's a problem associated with the IBOutlet not being linked properly to the button as nibs use KVC under the hood. You may also need to connect the root view of the nib to an IBOutlet in your UIView subclass.
Check out my other post here if you need more info on how to load UIView subclasses from nibs
UIView is not showing up in UIScrollView

Related

Using xib programatically setting IBOutlet and file owner results in key value coding-compliant error

I create a xib. The file owner of the xib is a set to a custom class called PackageTrackingListViewElement. The PackageTrackingListViewElement has an IBOutlet property called contentView, among others. Several views in interface builder are connected to the IBOutlet properties of the custom class called PackageTrackingListViewElement.
I try to initialize an object from the xib.
PackageTrackingListViewElement *element2 = [[[NSBundle mainBundle] loadNibNamed:#"PackageTrackingListViewElementXib" owner:nil options:nil] objectAtIndex:0];
[element2.labelDate setText:#"12/14/15"];
[element2.labelLocation setText:#"Berkeley, California"];
After this, I add the element2 object to a UIStackView.
What am I supposed to set the file owner in loadNibNamed so that I do not get the error that the owner of the xib is not key-value compliant for the properties I am attempting to access?
My error is [<UIStackView 0x165ddc80> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key contentView.' When I try to set the stackView as the owner of the xib. I know this is wrong of course, but I cannot set the object which has not been created to be its own owner. I do not understand what to do.
Alas figured it out. Many thanks to Instantiating a UIView from a XIB file with itself as the file's owner?
Thank you nebs
PackageTrackingListViewElement.h
#import <UIKit/UIKit.h>
#interface PackageTrackingListViewElement : UIView
#property (nonatomic,strong) IBOutlet UILabel *labelLocation;
- (instancetype)initFromNib;
#end
PackageTrackingListViewElement.m
#import "PackageTrackingListViewElement.h"
#implementation PackageTrackingListViewElement : UIView
- (instancetype)initFromNib {
return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:nil options:nil] firstObject];
}
#end
You can then simply do:
PackageTrackingListViewElement *myView = [[PackageTrackingListViewElement alloc] initFromNib];
[myView.labelLocation setText:#"text"]; //access properties
By using the instantiation procedure in the link above, I got my instantiation of the xib to work. I set the file-owner of the xib to nothing (NSObject), and instead set the root view (by selecting the view in the xib) to the PackageTrackingListViewElement and connecting all outlets to that view.

UICollectionReusableView Section Header crashes because of IBOutlet connection

I have a UICollectionViewController which delegates UICollectionViewDataSource and UICollectionViewDelegate. My collection view displays 2 sections with multiple rows of data and works fine.
I have created a Section Header (in IB Attributes Inspector -> Accessories) which then subclasses UICollectionReusableView with the SWOHighScoreHeader class:
#interface SWOHighScoreHeader : UICollectionReusableView
#property (strong, nonatomic) IBOutlet UILabel *hiScoreHead;
#end
I set this class (SWOHighScoreHeader) as the Custom Class for the UICollectionReusableView in IB.
In the UICollectionViewController I use the method:
-(UICollectionReusableView*)collectionView:(UICollectionView*)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
SWOHighScoreHeader *highScoreHeaderView = nil;
if ([kind isEqual:UICollectionElementKindSectionHeader]) {
highScoreHeaderView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
withReuseIdentifier:#"highScoreTableHead"
forIndexPath:indexPath];
}
return highScoreHeaderView;
}
The identifier highScoreTableHead is set as the UICollectionReusableView Collection Reusable View Identifier in IB.
At this stage, the section headers display correctly, albeit with the default label text.
My issue comes when I connect the IBOutlet UILabel hiScoreHead property with the outlet in IB. When I do this, the program crashes with:
Unknown class SWOHighScoreHeader in Interface Builder file.
** * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key submitButton.'
I've tried deleting the outlet connection and reconnecting but still nothing. Any ideas where I am going wrong?
Add the following property to SWOHighScoreHeader:
#property (weak) IBOutlet UIButton* submitButton;
Or try to find out which object in your storyboard is expecting the submitButton to actually exist.
An IBoutlet must always be a weak property, otherwise its container will not be deallocated.
I solved this by using Tags instead of IBOutlets ie
UILabel *hiScoreHeader = (UILabel *)[highScoreHeaderView viewWithTag:101];
hiScoreHeader.text = #"Header Text";
I'm not sure why the IBOutlets don't work but at least I have a solution.

UICollectionView, UICollectionCell and IBOutlet

I have two separate xib. One hold main screen as child of UIView and also UICollectionView. Second xib contains UICollectionCell. If I just run my code as it is, it is working. (First xib with UIView is used in storyboard, its places in UIViewController).
I have this in - (void) awakeFromNib
UINib *cellNib = [UINib nibWithNibName:#"ViewCellNIB" bundle:nil];
[self.todayScroll registerNib:cellNib forCellWithReuseIdentifier:#"TodayCellID"];
Now, I want to add some IBOutlet connections into ViewCellNIB. If I do this, my code crash in runtime with this error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0xb068b10> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key temporaryLabel.'
I have this:
#property (weak, nonatomic) IBOutlet UILabel *temporaryLabel;
connected to UILabel on UICollectionViewCell
How can I repair this ?
Ok.. I have found solution. My mistake. I have incorrectly connect IBOutlet in Designer. I have to connect outlets via main UICollectionViewCell and not directly by dragging connection from element to code.

This class is not key value coding-compliant for the key Picker

I added a view to my app that I open from a button and can't find what I'm doing wrong.
I triple checked that dataSource & delegate are connected to File's Owner
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<HelpViewController 0xab58980> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Picker.'
The code in my viewcontroller.h
#interface LanguageSelectionViewController : UIViewController {
IBOutlet UILabel *label;
IBOutlet UIPickerView *Picker;
NSArray *PickerData;
}
#property (retain, nonatomic) IBOutlet UIPickerView *Picker;
#property (retain, nonatomic) NSArray *PickerData;
#end
Anyone got a solution or a tip in the right direction?
Go to your storyboard click the helpviewcontroller (the whole thing so you have a blue outline around the view) now with the utility toolbar (toolbar on the right) click the arrow (the right most icon) you should see a ! mark on one of the connections. Delete that and it should work.

confused difference between Custom Class for an Object and for the File's Owner and steps via IB

This is another "I'm confused question". So I'm working on bringing in custom views into a view controller. I'll just outline the exact steps for the error.
Create a Single View Application Project
Create a Nib File via File -> New -> User Interface -> View; call it theNIB.xib. Add a simple label to make sure loading.
add following code:
UIView *view = [[[NSBundle mainBundle] loadNibNamed:#"theNIB" owner:self options:nil] objectAtIndex:0];
view.frame=CGRectMake(10.0f,10.0f,100.0f,100.0f);
view.backgroundColor=[UIColor orangeColor];
[self.view addSubview:view];
This works.
Now what I want to do is connect this nib with a UICustomView so I create ArcView via File -> New -> UIView.
'4. In IB, I need to connect theNIB to ArcView so I highlight the File's Owner in the Placeholders and select AcrView in the Custom Class.
'5.' Then I select the main View and set it to ArcView in the Custom Class.
I am at a loss for what the next step is or whether 4 or 5 were necessary (both / neither)? Do I try to make an outlet reference in ArcView to view for the main View in Interface Builder? Should I be able to Alt-drag from the View to the header file in assistant editor (I am not currently able to)?
thx in advance
** edit 1 **
Here's the File's Owner with arcView set:
View object with arcView not set:
Define an IBOutlet #property in your parent class's #interface section like this:
#property (weak, nonatomic) IBOutlet ArcView *arcView
Then go into Interface Builder, and right click on File's Owner. When you see "arcView" in the black HUD window, drag the mouse from that item to your view on the XIB.
Now you have a property for your arcview control, and you can utilize it just like you would any control such as UIButton, UILabel etc.
Set the file's owner == your UIView subclass so that you can connect outlets to it. And you should set the class of nib-painted UIView to that same subclass because it's an instance of that UIView subclass.
In other words, follow these steps:
create a UIView subclass called CustomView
create a UIView xib New File -> User Interface -> View
change the file's owner to CustomView
change the view's class to CustomView
add subviews if you wish, connect them as outlets to the files owner (CustomView)
Your crash is happening because your code says this:
UIView *view = [[[NSBundle mainBundle] loadNibNamed:#"theNIB" owner:self options:nil] objectAtIndex:0];
But that owner:self is the view controller where this code is running. You want the view subclass to be the nib's owner.
To fix, give your UIView subclass the job of init-ing itself from the nib, like this:
CustomView.h
#interface CustomView : UIView
- (id)initFromNib;
#end
CustomView.m
#import "CustomView.h"
#interface CustomView ()
// connect this in the XIB to file's owner that you've set to this CustomView class
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
#implementation CustomView
- (id)initFromNib
{
self = [[[NSBundle mainBundle] loadNibNamed:#"CustomView" owner:self options:nil] objectAtIndex:0];
if (self) {
// prove you can set properties on your outlets
self.myLabel.text = #"this is good";
}
return self;
}
I built a little project with just this stuff in it as described. Works fine. Lemme know if you'd like to see it and I'll find a way to send you an anonymous zip.

Resources