我遇到了一个由XIB文件定义的视图的严重问题。这是一个简单的数字输入板,按钮为0-9:
问题是在极少数情况下(如上面的屏幕截图所示),缺少按钮标签。它并不总是相同的标签(在上面的示例中,缺少“0”)。通常关闭视图并重新创建它可以解决问题。
XIB文件的按钮附加到视图中的UIButton控件。视图构造如下:
@property (nonatomic,strong) IBOutlet UIButton *button0;
// etc...
@property (nonatomic,strong) IBOutlet UIButton *button9;
- (id)initWithFrame:(CGRect)frame
{
self = [[UINib nibWithNibName:[[self class] description] bundle:nil]
instantiateWithOwner:nil
options:nil
][0];
if (self)
{
self.frame = frame;
// ...
}
return self;
}
没有涉及控制器,我也不希望这样。
视图是用以下代码创建的:
CustomView *view = [[CustomView alloc] initWithFrame:frame];
当问题发生时(通常不是随机的),用户点击带有缺失标签的按钮,按钮的titleLabel.text属性为nil
:
- (IBAction) numberButtonPressed:(UIButton *)button
{
NSLog("button label = %@",button.titleLabel.text);
// output: button label = (null)
}
XIB文件的XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5056" systemVersion="13C64" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment defaultVersion="1536" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1" customClass="AmountEntryView">
<rect key="frame" x="0.0" y="0.0" width="242" height="345"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="3" customClass="UIButton">
<rect key="frame" x="0.0" y="56" width="80" height="56"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.80112777219999998" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="40"/>
<state key="normal" title="7">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="numberButtonPressed:" destination="1" eventType="touchUpInside" id="142"/>
</connections>
</button>
<!-- ALL OTHER BUTTONS (omitted, as they are identical) -->
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="0.00" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="107">
<rect key="frame" x="0.0" y="0.0" width="242" height="56"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.91557459679999997" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="32"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.72580645160000001" alpha="1" colorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="button0" destination="86" id="108"/>
<outlet property="button1" destination="58" id="109"/>
<outlet property="button2" destination="60" id="110"/>
<outlet property="button3" destination="59" id="111"/>
<outlet property="button4" destination="30" id="112"/>
<outlet property="button5" destination="32" id="113"/>
<outlet property="button6" destination="31" id="114"/>
<outlet property="button7" destination="3" id="115"/>
<outlet property="button8" destination="19" id="116"/>
<outlet property="button9" destination="8" id="117"/>
<outlet property="buttonBack" destination="105" id="118"/>
<outlet property="buttonDone" destination="106" id="119"/>
<outlet property="buttonDot" destination="94" id="120"/>
<outlet property="labelAmount" destination="107" id="133"/>
</connections>
</view>
</objects>
</document>
我不知道为什么会出现这个问题,而且我在网上或网站上的任何其他地方都找不到类似的报道。
答案 0 :(得分:2)
设置标签时使用:
[self.button0 setTitle:@"0" forState:UIControlStateNormal];
不
self.button0.titleLabel.text = @"0";
此方法不会保留标题集,即旋转设备后标题会消失等。
其他可能的原因:
减小UIButtons中字体的大小。如果用户使用 设置使用大动态字体大小,然后文本可能会变为 大到适合。
在没有XIB的代码中设置UIView。
<强>旁注:强> 您也可以通过标签引用按钮,然后您的代码将变得更简单,因为您不必单独连接每个按钮。
答案 1 :(得分:1)
正如我在评论中所说,你的问题真的很奇怪,但这不是我第一次需要从头开始重新创建一个xib,导致一些奇怪的问题。
一旦有人告诉我不要在init方法中交换self
,即使我认为这不会解决问题,我也想给你两种不同的加载xib的方法。
第一个:
可能只是改变一行代码就可以尝试。假设在你的xib中,视图具有自定义类CustomView
,并且这里的插座已连接,文件所有者为零。尝试加载如下:
CustomView *view =[[UINib nibWithNibName:[NSStringFromClass(self.class) bundle:nil] instantiateWithOwner:nil options:nil][0];
这将从xib触发加载过程并且它获取其根对象,与表视图中的单元原型可能使用的相同。如果您需要进行某种初始化,请在-awakeFromNib
内进行,因为initWithFrame
将不会被调用。
获取类名的正确方法不是-description
,因为它只是提供关于对象的信息,将来它可以改变(不太可能),NSStringFromClass
只是将类名称作为字符串。
第二个:
创建一个xib,将文件所有者设置为CustomView实例,与fil的所有者建立连接,加载xib并将其添加为子视图。
这是一个小类,我用它作为抽象类来创建使用xib的视图。
@interface NibbedView : UIView
@property (strong, nonatomic) IBOutlet UIView * nibView;
- (instancetype) initWithNibName: (NSString*) nibViewName;
- (instancetype) initWithFrame:(CGRect)frame andNibName: (NSString*) nibViewName;
- (void) loadNibWithName: (NSString*) nibName;
@end
和实施:
@interface NibbedView ()
@end
@implementation NibbedView
-(void) setContstraints {
_nibView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_nibView);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_nibView]|" options:0 metrics: 0 views:viewsDictionary]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_nibView]|" options:0 metrics: 0 views:viewsDictionary]];
}
- (instancetype) initWithNibName: (NSString*) nibViewName{
if (self = [self initWithFrame:CGRectZero]) {
if (nibViewName) {
[self loadNibWithName:nibViewName];
}
}
return self;
}
- (instancetype) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
//
}
return self;
}
- (instancetype) initWithFrame:(CGRect)frame andNibName: (NSString*) nibViewName{
if (self = [self initWithFrame:frame]) {
if (nibViewName) {
[self loadNibWithName:nibViewName];
}
}
return self;
}
- (void) loadNibWithName: (NSString*) nibName {
if (_nibView) {
[_nibView removeFromSuperview];
}
else {
[[NSBundle mainBundle] loadNibNamed: nibName owner: self options: nil];
_nibView.frame = self.bounds;
[self addSubview:_nibView];
[self setContstraints];
}
}
@end
它使用自动布局使xib视图遍布CustomView根视图
正如我所说,尝试在调试器中创建根视图的-recursiveDescription
,即使没有连接,也许是在层次结构中的某个位置。
答案 2 :(得分:0)
我无法确切地说出导致您描述的行为的原因,但我想建议一种方法来尝试找到正在发生的事情的线索,因为您无法共享您的项目。您可以尝试以下任何一种方法,所有方法都旨在找出text
何时成为nil
;我按照日益复杂的顺序列出它们:
为button.titleLabel.text
属性添加KVO观察者;如果这不起作用,
使用您自己的实现调整UILabel
setText:
方法;如果这不起作用,
进入调试器并在button.titleLabel.text
的内存位置设置监视(对于您的所有按钮,在创建时)。
希望,当text
变为nil
时,其中一种方法会让您进入应用程序,这样通过检查调用堆栈,您可以找出导致问题的原因。
希望它有所帮助。
答案 3 :(得分:0)
检查一下 [self.view bringSubviewToFront:button0];
可能会帮到你。
答案 4 :(得分:-1)
我从来没有加载或看到像这样加载笔尖的人。
尝试使用更标准的[NSBundle.mainBundle loadNibNamed:owner:options:]
。
答案 5 :(得分:-1)
在XIB中,检查您的UIButtons
所有Title
属性设置为Plain
而不是Attributed
。
问题是按钮或标签的text
与其attributedText
不同,如果两者都已设置,则有时根本不显示任何文字。尝试对此进行测试以查看是否存在任何属性文本:
- (IBAction)numberButtonPressed:(UIButton *)button {
NSLog(@"%@", self.setButton.titleLabel.attributedText);
}
使用属性与纯文本之间的区别是:
[self.button0 setAttributedTitle:[[NSAttributedString alloc] initWithString:@"0"] forState:UIControlStateNormal];
[self.button0 setTitle:@"0" forState:UIControlStateNormal];
答案 6 :(得分:-1)
使用weak
代替IBOutlets
代替strong
。如果没有访问完整的代码并进行一些调试,我无法提供任何具体的解释,但IBOutlet
s通常应该是weak
属性。假设,当视图正在进行优化以显示具有strong
引用的子视图时,可能会以某种方式破坏指针,这就是为什么当你需要访问按钮时你会得到nil。