iOS Instantiate Custom View from Nib File across multiple UIViewController - ios

I need an example of how to instantiate a custom view from a nib file. i wrapped my head around several stackoverflow posts but i didn't get it. Maybe i only need a hint how to do it.
what I want to do is - creating a custom view with interface builder. it should be a template so that i can instantiate it multiple times to add it to multiple view controllers.
So far I have created my custom view xib file called MyIssueView.xib. Which consists in fact just of the main view and some labels.
And I created a Subclass of UIView which is called IssueView with the Outlets for my labels in the MyIssueView.xib.
How do I now hook up the outlets with the IB? And how can I instantiate the IssueView from any ViewController?
Would be glad for an example!
Cheers.
UPDATE:
I now have
IssueView.xib
IssueView.h (UIView Subclass)
IssueView.m
My IssueView.h:
#import <UIKit/UIKit.h>
#interface IssueView : UIView
#property (weak, nonatomic) IBOutlet UILabel *label1;
#property (weak, nonatomic) IBOutlet UILabel *label2;
#property (weak, nonatomic) IBOutlet UILabel *label3;
#property (weak, nonatomic) IBOutlet UILabel *label4;
#end
My IssueView.m:
#import "IssueView.h"
#implementation IssueView
#end
My ViewController.m:
#import "AllIssuesViewController1.h"
#import "IssueView.h"
#import "UIView+NibLoading.h"
#interface AllIssuesViewController1 ()
#end
#implementation AllIssuesViewController1
- (void) loadView
{
}
- (void)viewDidLoad
{
[super viewDidLoad];
_issueView = [IssueView loadInstanceFromNib];
}
It gives me an error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x8292580> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label1.'

I have a category that extends UIView called UIView+NibLoading.
In it is this code...
#import "UIView+NibLoading.h"
#implementation UIView (NibLoading)
+ (id)loadInstanceFromNib
{
UIView *result;
NSArray* elements = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id anObject in elements) {
if ([anObject isKindOfClass:[self class]]) {
result = anObject;
break;
}
}
return result;
}
#end
Then when I want to instantiate a UIView subclass from a nib I just import the category and I can run...
self.issueView = [IssueView loadInstanceFromNib];\
You need to connect the labels like this...
If you connecting the labels to "File's Owner" then you'll need to remove those connections.

Related

How to have a single IB Outlet for 2 UIViews

I'm currently developing an application that displays ads. The main view controller has 2 UIViews that act as containers for the ad views that will be passed in when they are loaded. However, I'm using an API that only takes a single "adContainer" as a parameter, so tried using an IBOutlet Collection called adContainer that has each of these 2 UIViews (adContainer1 and adContainer2) linked to it. I tagged each of these so that on the main view controller when I try to load an ad, I can iterate through the adContainers in the IBOutlet Collection and request each adContainer individually based on the object's tag. I'm being thrown this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance
Here is the code for my viewController.h :
#import <UIKit/UIKit.h>
#import "MPAdView.h"
#import "MPViewController.h"
#class MPAdInfo;
#interface MPSmaatoScrollBannerAdDetailViewController :
UIViewController <MPAdViewDelegate>
#property (weak, nonatomic) IBOutlet UILabel *titleLabel;
#property (weak, nonatomic) IBOutlet UILabel *IDLabel;
#property (weak, nonatomic) IBOutlet UILabel *failLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
#property (strong, nonatomic) IBOutletCollection(UIView) NSArray
*adViewContainer;
- (id)initWithAdInfo:(MPAdInfo *)info;
#end
And here is the function in my viewController.m that I suspect is throwing the error:
- (void)configureAd
{
for (UIView *ad in _adViewContainer) {
if (ad.tag == 1) {
self.adView1 = [[MPSampleAppInstanceProvider sharedProvider] buildMPAdViewWithAdUnitID:self.info.ID
size:ad.bounds.size];
self.adView1.delegate = self;
self.adView1.accessibilityLabel = #"smaato banner";
self.adView1.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[ad addSubview:self.adView1];
[self.adView1 stopAutomaticallyRefreshingContents];
} else if (ad.tag == 2) {
self.adView2 = [[MPSampleAppInstanceProvider sharedProvider] buildMPAdViewWithAdUnitID:self.info.ID
size:ad.bounds.size];
self.adView2.delegate = self;
self.adView2.accessibilityLabel = #"smaato banner";
self.adView2.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[ad addSubview:self.adView2];
[self.adView2 stopAutomaticallyRefreshingContents];
}
}
}
Please help! Thank you in advance!
According to the way you said, I did not report an error myself; it may be that your xib cable is not set correctly.
You can refer to this:
"countByEnumeratingWithState:objects:count:" Error

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.

FBLogin assign delegate from UIView

I have a FBLogin (Facebook SDK) button I am using in a view being replicated throughout many of my view controllers. It seems I cannot set a UIView as a delegate to the Facebook SDK, so I am trying to create a seperate ViewController to handle the delegate functions of the Facebook SDK.
Header file:
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#class AppDelegate, FBDelegateViewController;
#interface UserView : UIView {
AppDelegate *appDelegate;
IBOutlet UIView *contentView;
IBOutlet UIImageView *userImage;
IBOutlet UILabel *firstName;
FBDelegateViewController *fbDelegate;
IBOutlet FBLoginView *FacebookLogin;
}
#property (nonatomic, strong) IBOutlet UIView *contentView;
#property (nonatomic, strong) IBOutlet UILabel *firstName;
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) FBDelegateViewController *fbDelegate;
Currently in my implementation I am doing the following:
#import "UserView.h"
#import "AppDelegate.h"
#import "FBDelegateViewController.h"
#import <FacebookSDK/FacebookSDK.h>
#implementation UserView
#synthesize contentView, firstName, appDelegate, fbDelegate;
- (void)awakeFromNib {
fbDelegate = [[FBDelegateViewController alloc] init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[[NSBundle mainBundle] loadNibNamed:#"UserView" owner:self options:nil];
[self addSubview:self.contentView];
[userImage.layer setCornerRadius:21.5];
[FacebookLogin setDelegate:fbDelegate];
}
#end
The application crashes with the following:
** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setDelegate:]: unrecognized selector sent to instance 0xa5e4f80'*
In interface builder the UIView that contains the FBLogin item is set.
I also tried delegation with the UIView as well, but it looks like a UIView cannot be a delegate for a FBLogin?
Sorry, new territory here. Typically have used the associated view controller as a delegate - but want to understand external delegation.
It seems I cannot set a UIView as a delegate to the Facebook SDK, so I
am trying to create a seperate ViewController to handle the delegate
functions of the Facebook SDK.
This assumption is false, any NSObject can be set as the delegate as long as it implements the FBLoginViewDelegate protocol
This can be done like this:
#interface UserView : UIView <FBLoginViewDelegate> {
After you do this, you can set this view as the delegate!

Change UILabel text of custom UIView doesn't work

I have a custom UIView which was build with xib that have a file owner called CustomModuleUIView which contains labels and buttons . I have called this custom view in my Rootviewcontroller and I succeeded to display it using initWithCoder method. The problem is that I can't change the default text of UILabel neither from customMouleUIView nor from the root ViewController. I found example that tells me to do custom initialisation in in initWithCoder but it doesn't work for me and nothing changes and without any error it displays the default text.
This is my custom UIView xib
This is my root view controller
This is my code oh custom UIView .h
#import <UIKit/UIKit.h>
#interface ModuleCustomUIView : UIView
-(void) setup;
#property (weak, nonatomic) IBOutlet UIImageView *_moduleIcon;
#property (retain, nonatomic) IBOutlet UILabel *_moduleName;
- (IBAction)openDemo:(id)sender;
- (IBAction)close:(id)sender;
#property (weak, nonatomic) IBOutlet UIImageView *_moduleImage;
#property (strong, nonatomic) IBOutlet UILabel *_positionLabel;
#end
code of .m , i use setup method to init my UIView because I couldn't call
[[NSBundle mainBundle] loadNibNamed:xib owner:self options:nil] ;
inside initWithCoder that causes infinite loop .
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
}
return self;
}
-(void) setup
{
NSString *xib= #"CustomUIView";
NSArray *array=[[NSBundle mainBundle] loadNibNamed:xib owner:self options:nil] ;
UIView *view =[array objectAtIndex:0];
//code that doesn't work
[_positionLabel setText:#"hello world"];
//
[self addSubview:view];
}
this is my root view controller .h
- (void)viewDidLoad
{
[super viewDidLoad];
[_moduleCustomView setup];
[self.view addSubview:_moduleCustomView];
//code doesn't work
[_moduleCustomView setText:#"hello world"];
}
even in the did load I can't change the text
I have found my mistake , it's about file owner , i have change it in the inspector but by selecting the uiview and not te file's owner , i change NSObject to my class name and reconnect the label .
I guess the Files Owner attribute should be your 'root viewcontroller'.

iOS 5 create custom UIButton reusable component with .XIB

I'm newbie in the iOS development and I'm working in a projecte that it uses iOS5 and Storyboarding. I would like to create a reusable component, like a button, with a custom view (inside the button there will be some images and labels, it will be a big button), to create some of them in the same view of a Storyboard.
So I've created a XIB file (ItemClothes.xib) with a UIButton and inside of it some UIImagesViews and a UILabel. Then I've created a subclass of UIButton (UIItemClothes.h and UIItemClothes.m), with properties for UIImageViews and UILabel components.
UIItemClothes.h
#import <UIKit/UIKit.h>
#import "SCClothes.h"
#interface UIItemClothes : UIButton
#property (nonatomic, strong) IBOutlet UIImageView *imageClothes;
#property (nonatomic, strong) IBOutlet UIActivityIndicatorView *loadingImage;
#property (nonatomic, strong) IBOutlet UIImageView *seasonIconClothes;
#property (nonatomic, strong) IBOutlet UIImageView *categoryIconClothes;
#property (nonatomic, strong) NSString *idClothes;
#property (strong, nonatomic) IBOutlet UILabel *lblProva;
#end
UIItemClothes.m
#import "UIItemClothes.h"
#implementation UIItemClothes
#synthesize imageClothes = _imageClothes;
#synthesize loadingImage = _loadingImage;
#synthesize seasonIconClothes = _seasonIconClothes;
#synthesize categoryIconClothes = _categoryIconClothes;
#synthesize idClothes = _idClothes;
#synthesize lblProva = _lblProva;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:#"ItemClothes" owner:self options:nil] objectAtIndex:0]];
}
return self;
}
#end
Then in the .XIB file I've set the class of UIButton as UIItemClothes, and make the relationships between XIB's UI components and my class properties.
So, after that, in the Storyboard, in the ViewController of one view I've written this code:
UIItemClothes *item = [[UIItemClothes alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 200.0)];
item.lblProva.text = #"test!";
[item.categoryIconClothes setImage:iconCategory];
item.seasonIconClothes.image = iconSeason;
[cell addSubview:item];
As you see, this component will be inside a TableViewCell, and the idea is to put more components (UIItemClothes) inside of it.
The problem is that the component is drawed but any outlet is set as I do in the code above.
Can anyone help me?
Thanks!
well, the problem has been resolved... Instead of having a custom subclass of UIButton, there will be needed a ViewController with all Outlets. Then in the other ViewController (StoryBoard) is initialized this new ViewController

Resources