从Nib文件中获取项目的新方法。
以下答案中的示例。
这个新答案是此项目的最新变化和问题
我想创建一个UIView子类,我想为UIView创建一个Interface构建器文件。我如何将文件所有者连接到自身。我希望能够设计视图并让它创建连接,但我不需要视图控制器。
除了将nib加载到数组中之外,我可以使用nib文件作为视图本身的连接器吗?
我希望我正确地问这个问题。我会详细说明。
创建UIViewController我可以选择为它创建一个xib文件。那时我可以将UIViews添加到xib中并进行连接。但是文件所有者似乎没有与其关联的UI编辑器,所以我想创建一个UIView,它将成为另一个视图中的子视图。我真的不想用代码创建它,因为手动布局项目很痛苦。所以我想使用相同的构造来创建一个小的uiview以放入另一个
修改
当我找到另一种更好的加载nib类的方法时,我再次编辑了这个。我想一些用户希望看到的堆栈溢出。
我想找到一种从笔尖加载UIView的优雅方法。并且来自堆栈溢出用户PeyloW的一些信息我已经设法做到这一点。
我将发布我的结果,因为信息将导致一个解决方案,但这个解决方案对我来说非常优雅。
我的新头文件。
(导入的每个头文件都与单个xib文件中的项相关联。)
#import <Foundation/Foundation.h>
#import "TitleCell.h"
#import "ToggleCell.h"
#import "ButtonCell.h"
#import "TextCell.h"
@interface TableViewCells : NSObject {
UINib *uiNibHolder;
}
@property (nonatomic, readonly) NSArray *nibArray;
// These are the classes that will be loadable.
- (TitleCell*) titleCell;
- (ToggleCell*) toggleCell;
- (ButtonCell*) buttonCell;
- (TextCell*) textCell;
- (id) loadViewByClass: (id) viewClass;
@end
和类文件。
loadViewByClass:是在nib文件中查找项目的方法 便捷存取器具有正确的类型,可以将类对象实例化 注意:我不建议将一堆视图加载到此中,加载的视图越多,加载nib文件时必须创建的视图越多。
#import "TableViewCells.h"
@implementation TableViewCells
@synthesize nibArray;
- (void) unloadProperties{
[uiNibHolder release];
}
- (NSArray *)nibArray{
return [uiNibHolder instantiateWithOwner:nil options:nil];
}
- (id) init{
if ((self = [super init]))
{
// Im using the class name for the Xib file.
// This means it will look in TableViewCells.xib
// You can change the class name, or pass a Nib name to this class
uiNibHolder = [[UINib nibWithNibName:[[self class] description] bundle: [NSBundle mainBundle]] retain];
}
return self;
}
- (TitleCell *)titleCell{
return [self loadViewByClass:[TitleCell class]];
}
- (ToggleCell *)toggleCell{
return [self loadViewByClass:[ToggleCell class]];
}
- (ButtonCell *)buttonCell{
return [self loadViewByClass:[ButtonCell class]];
}
- (TextCell *)textCell{
return [self loadViewByClass:[TextCell class]];
}
- (id)loadViewByClass:(Class)viewClass{
for (id item in self.nibArray)
{
if ([item isKindOfClass:viewClass])
{
return item;
}
}
return nil;
}
- (void)dealloc{
[self performSelector:@selector(unloadProperties)];
[super dealloc];
}
@end
能够按班级加载是非常好的。如果该类不在xib文件中,则返回nil。
这可以适用于使用多个nib文件,具体取决于您加载的视图类型。使用延迟加载属性技术,您可以仅在需要时加载这些笔尖,使内存占用空间小,并且仍然允许您通过一个方便的类加载器加载类。
作为演示,我使用TableView加载了一小撮视图
@synthesize tableViewCellLoader = _tableViewCellLoader;
- (TableViewCells *)tableViewCellLoader{
if (_tableViewCellLoader == nil){
_tableViewCellLoader = [[TableViewCells alloc] init];
}
return _tableViewCellLoader;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
switch (indexPath.row) {
case 0:
return self.tableViewCellLoader.toggleCell;
break;
case 1:
return self.tableViewCellLoader.textCell;
break;
case 2:
return self.tableViewCellLoader.titleCell;
break;
case 3:
return self.tableViewCellLoader.buttonCell;
break;
}
return nil;
}
正如你所看到的,我懒得加载我的TableViewCellLoader,如果我想,我只能在调用它们的类时使TableViewCells类延迟加载UINib对象。
我喜欢代码方便。
仍然, 再次感谢PeyloW。
答案 0 :(得分:1)
文件所有者只是一个代理对象,不需要在运行时指定,但在Interface Builder中的设计时始终可见。
如果您不需要,可以忽略连接文件所有者的任何内容。 at运行时使用以下内容加载NIB文件:
NSArray* rootObject = [[NSBundle mainBundle] loadNibNamed:@"MyNib"
owner:nil
options:nil];
为owner
参数传递的内容是加载nib时作为文件所有者代理传递的内容,nil
工作正常。
rootObject
数组包含所有根级别对象,但不包含代理。请注意,数组是自动释放的,因此如果您需要加载的对象留在周围,则必须保留数组,或者只保留您感兴趣的特定元素。
使用loadNibNamed:owner:options:
并不是IO绑定。如果需要性能,那么您应该使用UINib
的实例来缓存内存中的NIB文件并从中实例化对象。
UINib* myNib = [[UINib nibWithNibName:@"MyNib"
bundle:[NSBundle mainBundle]] retain];
// And then instantiate using:
NSArray* rootObject = [myNib instantiateWithOwner:nil
options:nil];
答案 1 :(得分:0)
您可以这样做,但没有理由不能在UIView中创建IBOutlets并直接连接到它们。因此,在xib文件中,您将拥有一个根UIView,请确保将该类更改为您的自定义类。然后,您可以直接在视图上设置插座,不需要使用文件所有者。
答案 2 :(得分:0)
我的最新答案
经过很长时间并且玩这种可能性后,我尝试了许多场景并得出结论,最好的方案是为每个请求创建UINib并获取相关对象。一次通过可以获得最佳效果。如果你有一个你计划经常使用的对象,最好将它放入自己的nib中,而不是在具有多个不同类的nib中,因为每次初始化UINib时都会创建每个类。
这是我用来完成这项任务的课程。
LSObjectLoader.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface LSObjectLoader : NSObject {
UINib *nibHolder;
NSString *currentNibName;
NSArray *nibArray;
}
- (id) loadViewFromNib: (NSString*) nibName ofClassType:(Class) classType;
@end
LSObjectLoader.m
//
// LSObjectLoader.m
// APMobile
//
// Created by jason.mckinley on 2/8/12.
// Copyright (c) 2012 LoKi-Systems. All rights reserved.
//
#import "LSObjectLoader.h"
@implementation LSObjectLoader
- (id) loadViewFromNib: (NSString*) nibName ofClassType:(Class) classType
{
if (![currentNibName isEqualToString:nibName])
{
currentNibName = [nibName copy];
nibHolder = [UINib nibWithNibName:currentNibName bundle:[NSBundle mainBundle]];
}
nibArray = [nibHolder instantiateWithOwner:nil options:nil];
for (id item in nibArray)
{
if ([item isKindOfClass:classType])
{
return item;
}
}
return nil;
}
@end
最后有几种方法可以实现这一点。
方法1直接加载。
LSObjectLoader *oLoader = [[LSObjectLoader alloc] init];
MyClass *thisInstance = [oLoader loadViewFromNib:@"TableViewCells"
ofClassType:[MyClass class]];
方法2类加载
Nib文件“TableViewCells.xib”(包含“MyChatCell”类对象)
类文件“MyChatCell.h / MyChatCell.m”
标题
#import <UIKit/UIKit.h>
@interface MyChatCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UILabel *name;
@property (weak, nonatomic) IBOutlet UILabel *message;
@property (weak, nonatomic) IBOutlet UIImageView *image;
+ (MyChatCell*) newChatCell;
@end
实施
#import "MyChatCell.h"
#import "LSObjectLoader.h"
@implementation MyChatCell
+ (LSObjectLoader*) nibLoader{
static LSObjectLoader *_objectLoader;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_objectLoader = [[LSObjectLoader alloc] init];
});
return _objectLoader;
}
+ (MyChatCell *)newChatCell{
return [[self nibLoader] loadViewFromNib:@"TableViewCells" ofClassType:[self class]];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self){
// This is the init code for nib loading
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
方法3自定义加载程序类
Nib文件“MyChatCells.xib”(包含“MeChat”和“ThemChat”类对象)
班级档案“MyChatCells.h / MyChatCells.m”
标头文件
#import <UIKit/UIKit.h>
#import "MeChat.h"
#import "ThemChat.h"
@interface MyChatCells : NSObject
+ (MeChat*) newMeChat;
+ (ThemChat*) newThemChat;
@end
实施档案
#import "MyChatCells.h"
@implementation MyChatCells
+ (LSObjectLoader*) nibLoader{
static LSObjectLoader *_objectLoader;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_objectLoader = [[LSObjectLoader alloc] init];
});
return _objectLoader;
}
+ (MeChat*)newMeChat{
return [[self nibLoader] loadViewFromNib:NSStringFromClass([self class])
ofClassType:[MeChat class]];
}
+ (ThemChat*)newThemChat{
return [[self nibLoader] loadViewFromNib:NSStringFromClass([self class])
ofClassType:[ThemChat class]];
}
@end