Subtitles of UITableViewCell won't update Subtitles of UITableViewCell won't update ios ios

Subtitles of UITableViewCell won't update


As a temporary work around I simple introduced a blank space in the text label and programmatically where I set the label text to nil, I set it to a blank space

cell.detailTextLabel.text = @" ";

Adjust your logic accordingly to deal with a lone blank space as nil.

For me the detail text label didn't show up even though I had a string ready for it before the viewcontroller loaded. one of my many cells shows the current date in a detail text label as default whenever the view controller appears, but that didn't work either.

I think this has something to do with the fact that the iOS 8 is not able to update the text label's text if it set to nil initially.

So see to it that you introduce a blank space in your prototype cell as well, in interface builder. Surprisingly text in labels of my custom cells are working fine.


It appears Apple added an optimization which removes the detailTextLabel from the view hierarchy when the value is nil, and re-adds as necessary. Unfortunately in my tests, it gets added during a layout pass, but only after it would have been resized to fit the new text by that layout pass, so the size is still zero. The next layout pass (say on a rotation) then it will display OK.

One workaround may be to forcibly add the label back into the view hierarchy in all circumstances (seems like it should be OK if zero-sized). I'd be interested to see if dropping the below category into your app fixes things.

#import <objc/runtime.h>/* * In iOS8 GM (and beta5, unsure about earlier), detail-type UITableViewCells (the * ones which have a detailTextLabel) will remove that label from the view hierarchy if the * text value is nil.  It will get re-added during the cell's layoutSubviews method, but... * this happens just too late for the label itself to get laid out, and its size remains * zero.  When a subsequent layout call happens (e.g. a rotate, or scrolling the cells offscreen * and back) then things get fixed back up.  However the initial display has completely blank * values.  To fix this, we forcibly re-add it as a subview in both awakeFromNib and prepareForReuse. * Both places are necessary; one if the xib/storyboard has a nil value to begin with, and * the other if code explicitly sets it to nil during one layout cycle then sets it back). * Bug filed with Apple; Radar 18344249 . * * This worked fine in iOS7. */@implementation UITableViewCell (IOS8DetailCellFix)+ (void)load{    if ([UIDevice currentDevice].systemVersion.intValue >= 8)    {        /* Swizzle the prepareForReuse method */        Method original = class_getInstanceMethod(self, @selector(prepareForReuse));        Method replace  = class_getInstanceMethod(self, @selector(_detailfix_prepareForReuse));        method_exchangeImplementations(original, replace);        /*         * Insert an awakeFromNib implementation which calls super.  If that fails, then         * UITableViewCell already has an implementation, and we need to swizzle it instead.         * In IOS8 GM UITableViewCell does not implement the method, but they could add one         * in later releases so be defensive.         */        Method fixawake = class_getInstanceMethod(self, @selector(_detailfix_super_awakeFromNib));        if (!class_addMethod(self, @selector(awakeFromNib), method_getImplementation(fixawake), method_getTypeEncoding(fixawake)))        {            original = class_getInstanceMethod(self, @selector(_detailfix_awakeFromNib));            replace = class_getInstanceMethod(self, @selector(awakeFromNib));            method_exchangeImplementations(original, replace);        }    }}- (void)__detailfix_addDetailAsSubviewIfNeeded{    /*     * UITableViewCell seems to return nil if the cell style does not have a detail.     * If it returns non-nil, force add it as a contentView subview so that it gets     * view layout processing at the right times.     */    UILabel *detailLabel = self.detailTextLabel;    if (detailLabel != nil && detailLabel.superview == nil)    {        [self.contentView addSubview:detailLabel];    }}- (void)_detailfix_super_awakeFromNib{    [super awakeFromNib];    [self __detailfix_addDetailAsSubviewIfNeeded];}- (void)_detailfix_awakeFromNib{    [self _detailfix_awakeFromNib];    [self __detailfix_addDetailAsSubviewIfNeeded];}- (void)_detailfix_prepareForReuse{    [self _detailfix_prepareForReuse];    [self __detailfix_addDetailAsSubviewIfNeeded];}@end

There might be other approaches -- if you can call setNeedsLayout at the right time, it may force an additional layout pass which corrects things, but I was not able to find the right time for that.

EDIT: A comment below indicated that re-displayed cells could be an issue. So, a simpler fix may be to just swizzle layoutSubviews and do the check before calling Apple's implementation. That could solve all issues since it is during the layout call that the problem happens. So, below is that version of the fix -- I would be interested to see if that works.

#import <objc/runtime.h>@implementation UITableViewCell (IOS8DetailCellFix)+ (void)load{    if ([UIDevice currentDevice].systemVersion.intValue >= 8)    {        Method original = class_getInstanceMethod(self, @selector(layoutSubviews));        Method replace  = class_getInstanceMethod(self, @selector(_detailfix_layoutSubviews));        method_exchangeImplementations(original, replace);    }}- (void)_detailfix_layoutSubviews{    /*     * UITableViewCell seems to return nil if the cell type does not have a detail.     * If it returns non-nil, force add it as a contentView subview so that it gets     * view layout processing at the right times.     */    UILabel *detailLabel = self.detailTextLabel;    if (detailLabel != nil && detailLabel.superview == nil)    {        [self.contentView addSubview:detailLabel];    }    [self _detailfix_layoutSubviews];}@end

EDIT: It appears this bug is fixed in iOS9. So, the condition can be changed to:

if ([UIDevice currentDevice].systemVersion.intValue == 8)

If an application only needs to support iOS9 and above, the swizzle fix category can just be removed.


A few days passed and I think I'll have to use a workaround:

- (void) viewDidAppear:(BOOL)animated{  [super viewDidAppear:animated];  [self.without setNeedsLayout];}

This has a visible delay but it's the only way I could find to make the text appear and be readable on iOS8.