草庐IT

ios - Autolayout 动态高度 TableView 单元格在文本更改时呈现错误

coder 2024-01-24 原文

我有一个使用 AutolayoutiOS8 Dynamic Height 的自定义 UITableViewCell,包含两个不同大小的标签。上面的标签可以是 1 到 2 行,而底部标签总是只有 1 行。

:cellForRowAtIndexPath: 中,我将上部标签的文本设置为“Loading..”并调用一个方法从服务器(或缓存)检索实际文本(可能是任意长度)。第二个标签设置为其最终文本。

...
cell.title.text = @"Loading...";
cell.subtitle.text = source.name;

__weak NewsTableViewCell *weakCell = cell;
[[NewsManager sharedManager] getNewsForSource:source withBlock:^(NewsObject *object, NSError *error) {
    NewsTableViewCell *strongCell = weakCell;

    strongCell.title.text = object.articleHeadline;
}];
...

当方法返回并将文本从“正在加载...”更改为实际文本时,会发生以下三种情况之一:

  1. 一切都正确呈现。
  2. 移除第二个标签并将第一个标签固定到一行。
  3. 第一个标签被截去一半宽度(这通常发生在将手机侧转并再次变回竖屏后)。

我在 viewWillAppear: 中调用了 [self.tableView reloadData],因此如果出现错误,只需打开另一个 View 并返回此 View 即可解决问题。将手机转到另一侧,然后再回到原来的位置也是如此。

这是一张解释发生了什么的图片(注意:两个单元格应该像第二个一样):

下面是我如何使用 AutoLayoutStoryBoard 中设置 UITableViewCell:

我没有更改任何属性(例如拥抱和压缩优先级)。

谁能指导我正确的方向/让我知道我做错了什么?

编辑 1:这是一张照片,显示了 (1) 正确布局 (2) 错误布局 ( 3) 单元格等待它的最终文本时的布局(这会导致发生错误的布局)

编辑 2: 从 block 中调用 [strongCell setNeedsLayout][strongCell layoutIfNeeded] 不能解决我的问题,但会导致此 AutoLayout 错误出现在控制台中。你能帮我调试一下吗?

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you 
don't want. Try this: (1) look at each constraint and try to figure out which 
you don't expect; (2) find the code that added the unwanted constraint or 
constraints and fix it. (Note: If you're seeing 
NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the 
documentation for the UIView property 
translatesAutoresizingMaskIntoConstraints) 

(
"<NSLayoutConstraint:0x1700927a0 UILabel:0x127d39c20'Horrifying moment lioness...'.top == UITableViewCellContentView:0x127d2e510.topMargin>",
"<NSLayoutConstraint:0x170092930 V:[UILabel:0x127d39c20'Horrifying moment lioness...']-(8)-[UILabel:0x127d39dd0'Daily Mail Online']>",
"<NSLayoutConstraint:0x170092a70 UILabel:0x127d39dd0'Daily Mail Online'.bottom == UITableViewCellContentView:0x127d2e510.bottomMargin>",
"<NSLayoutConstraint:0x170092c00 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x127d2e510(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170092930 V:[UILabel:0x127d39c20'Horrifying moment lioness...']-(8)-[UILabel:0x127d39dd0'Daily Mail Online']>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

最佳答案

为了再次布局单元格,您需要使用 reload 方法重新加载单元格。

你可以这样实现...

首先,创建一个可变字典属性来存储单元格的文本...

@property (nonatomic, strong) NSMutableDictionary *textDictionary;

并在某处初始化它。

然后在行的单元格中...

更新了以下评论

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...

    cell.subtitle.text = source.name;

    // get the text from the dictionary
    NSString *titleText = self.textDictionary[source];

    if (titleText) {
        // second time through the text exists so just use it.
        cell.title.text = titleText;
    } else {
        // first time through the text is nil so set it to default and download it.
        cell.title.text = @"Loading...";

        // this just stops the download starting again before it has completed
        self.textDictionary[source] = @"Loading...";
    }

    // recheck the text and reload if it has changed
    [[NewsManager sharedManager] getNewsForSource:source withBlock:^(NewsObject *object, NSError *error) {
        NSString *oldText = self.textDictionary[source];
        NSString *newText = object.articleHeadline;

        // reload if the text has changed
        if (![oldText isEqualToString:newText]) {
            // store the text in the dictionary
            self.textDictionary[source] = newText;

            // reload the indexPath (will only trigger if the cell is visible)
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        }
    }];

    ....
}

第一次通过这个触发字符串的异步获取。完成后,它会将其存储在本地,然后重新加载该行。

第二次通过它将只获取本地存储的字符串并使用它而无需再次下载。

关于ios - Autolayout 动态高度 TableView 单元格在文本更改时呈现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30684220/

有关ios - Autolayout 动态高度 TableView 单元格在文本更改时呈现错误的更多相关文章

  1. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  2. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  3. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  4. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  5. ruby - Hanami link_to 助手只呈现最后一个元素 - 2

    我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm

  6. ruby - 在 Ruby 中动态创建数组 - 2

    有没有办法在Ruby中动态创建数组?例如,假设我想遍历用户输入的书籍数组:books=gets.chomp用户输入:"TheGreatGatsby,CrimeandPunishment,Dracula,Fahrenheit451,PrideandPrejudice,SenseandSensibility,Slaughterhouse-Five,TheAdventuresofHuckleberryFinn"我把它变成一个数组:books_array=books.split(",")现在,对于用户输入的每一本书,我想用Ruby创建一个数组。伪代码来做到这一点:x=0books_array.

  7. ruby - 单元测试文件 I/O 方法 - 2

    我对单元测试还是比较陌生。我用Ruby编写了一个类,它接受一个文件,在该文件中搜索给定的Regex模式,替换它,然后将更改保存回文件。我希望能够为此方法编写单元测试,但我不知道我将如何去做。有人能告诉我我们如何对处理文件i/o的方法进行单元测试吗? 最佳答案 看看这个HowdoIunit-testsavingfiletothedisk?基本上这个想法是一样的,文件系统是你的类的依赖。所以引入一个可以在你的单元测试中模拟的角色/接口(interface)(这样你在单元测试时就没有依赖性);角色中的方法应该是您从文件系统中需要的所有东西

  8. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  9. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  10. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

随机推荐