按钮标签在XIB支持的视图中消失

时间:2014-08-07 18:41:17

标签: ios objective-c uiview xib nib

我遇到了一个由XIB文件定义的视图的严重问题。这是一个简单的数字输入板,按钮为0-9:

Screenshot

问题是在极少数情况下(如上面的屏幕截图所示),缺少按钮标签。它并不总是相同的标签(在上面的示例中,缺少“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>

我不知道为什么会出现这个问题,而且我在网上或网站上的任何其他地方都找不到类似的报道。

7 个答案:

答案 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;我按照日益复杂的顺序列出它们:

  1. button.titleLabel.text属性添加KVO观察者;如果这不起作用,

  2. 使用您自己的实现调整UILabel setText:方法;如果这不起作用,

  3. 进入调试器并在button.titleLabel.text的内存位置设置监视(对于您的所有按钮,在创建时)。

  4. 希望,当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。