楊的回答是偉大的......但是「消息發送到釋放實例」尚可發生。我通過使用'自我'分配來解決這個問題。
所以如果你使用ARC,你將不得不允許這個'自我'分配。(有關更多信息,請參閱https://blog.compeople.eu/apps/?p=142)
要在ARC項目中實現此目的,請在文件中添加'-fno-objc-arc'標誌編譯器設置。 然後在此文件中進行NO-ARC編碼(如dealloc設置nils,調用超級dealloc等)。
另外,客戶端nib的viewcontroller應該使用strong屬性來存放由awakeFromNib返回的實例。在我的樣本代碼的情況下,被customView這樣引用:
@屬性(強,非原子)IBOutlet中CustomView * customView;
我終於加入了一些其他方面的改進,使用copyUIPropertiesTo性能處理和筆尖加載:和loadNibNamed在我的UIView +的Util類別定義。
所以awakeAfterUsingCoder:代碼現在
#import "UIView+Util.h"
...
- (id) awakeAfterUsingCoder:(NSCoder*)aDecoder
{
// are we loading an empty 「placeholder」 or the real thing?
BOOL theThingThatGotLoadedWasJustAPlaceholder = ([[self subviews] count] == 0);
if (theThingThatGotLoadedWasJustAPlaceholder)
{
CustomView* customView = (id) [CustomView loadInstanceFromNib];
// copy all UI properties from self to new view!
// if not, property that were set using Interface buider are lost!
[self copyUIPropertiesTo:customView];
[self release];
// need retain to avoid deallocation
self = [customView retain];
}
return self;
}
UIView的+的Util類的代碼是
@interface UIView (Util)
+(UIView*) loadInstanceFromNib;
-(void) copyUIPropertiesTo:(UIView *)view;
@end
是其實施
#import "UIView+Util.h"
#import "Log.h"
@implementation UIView (Util)
+(UIView*) loadInstanceFromNib
{
UIView *result = nil;
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;
}
-(void) copyUIPropertiesTo:(UIView *)view
{
// reflection did not work to get those lists, so I hardcoded them
// any suggestions are welcome here
NSArray *properties =
[NSArray arrayWithObjects: @"frame",@"bounds", @"center", @"transform", @"contentScaleFactor", @"multipleTouchEnabled", @"exclusiveTouch", @"autoresizesSubviews", @"autoresizingMask", @"clipsToBounds", @"backgroundColor", @"alpha", @"opaque", @"clearsContextBeforeDrawing", @"hidden", @"contentMode", @"contentStretch", nil];
// some getters have 'is' prefix
NSArray *getters =
[NSArray arrayWithObjects: @"frame", @"bounds", @"center", @"transform", @"contentScaleFactor", @"isMultipleTouchEnabled", @"isExclusiveTouch", @"autoresizesSubviews", @"autoresizingMask", @"clipsToBounds", @"backgroundColor", @"alpha", @"isOpaque", @"clearsContextBeforeDrawing", @"isHidden", @"contentMode", @"contentStretch", nil];
for (int i=0; i<[properties count]; i++)
{
NSString * propertyName = [properties objectAtIndex:i];
NSString * getter = [getters objectAtIndex:i];
SEL getPropertySelector = NSSelectorFromString(getter);
NSString *setterSelectorName =
[propertyName stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[propertyName substringToIndex:1] capitalizedString]];
setterSelectorName = [NSString stringWithFormat:@"set%@:", setterSelectorName];
SEL setPropertySelector = NSSelectorFromString(setterSelectorName);
if ([self respondsToSelector:getPropertySelector] && [view respondsToSelector:setPropertySelector])
{
NSObject * propertyValue = [self valueForKey:propertyName];
[view setValue:propertyValue forKey:propertyName];
}
}
}
後續,使這項工作在ARC下:http://blog.yangmeyer.de/blog/2012/07/09/an-update-on-nested-nib-loading/ – 2012-07-09 21:35:41