UICollectionView indexPath.row奇怪的行为(UICollectionView indexPath.row strange behaviour)
滚动我的一个collectionView时,我遇到了一个奇怪的问题。 当我打印
indexPath.row
从indexPath.row
正常,但最后一个indexPath.row
是3,然后如果我向后滚动它或者与excbadadress崩溃或以随机顺序打印1,2,4。 我假设我的代码中有错误但实际上不明白它在哪里。 这是我的代码:VC:func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize { if collectionView == mainEventsCollectionView { return CGSize(width: UIScreen.main.bounds.width - 40, height: 180) } else { return CGSize(width: 150, height: 200) } } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if collectionView == mainEventsCollectionView { return 3 } else { return 7 } } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView == mainEventsCollectionView { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainEventsCell", for: indexPath) as! MainEventCollectionViewCell cell.eventTitle.text = "Hello world".uppercased() cell.setupCell() return cell } else { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "importantEventsCell", for: indexPath) as! ImportantEventsCollectionViewCell print(indexPath.row) cell.setupCell() return cell } }
细胞:
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.roundCorners(.allCorners, radius: 6, borderColor: .clear, borderWidth: 0) } func setupCell() { self.content.backgroundColor = colorWithAlpha(.black, alpha: 0.7) self.eventDate.textColor = .white self.eventTime.textColor = .white self.eventName.textColor = .white if self.content.layer.sublayers!.count > 3 { self.content.layer.sublayers!.removeLast() } if self.eventDate.text == "Today" { self.content.backgroundColor = .clear DispatchQueue.main.async(execute: { self.content.drawGradient(colors: [UIColor(red: 250/255, green: 217/255, blue: 97/255, alpha: 0.7).cgColor, UIColor(red: 255/255, green: 135/255, blue: 67/255, alpha: 0.7).cgColor], locations: [0, 1]) }) self.eventDate.textColor = .black self.eventTime.textColor = .black self.eventName.textColor = .black } }
I'm having strange issue while scrolling one of my collectionViews. When I'm printing
indexPath.row
is goes ok from 0..6 but then lastindexPath.row
is 3, and then if I scroll back it either crashes with excbadadress or prints 1, 2, 4 in random order. I assume that I have and error in my code but really don't understand where is it. Here is my code: VC:func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize { if collectionView == mainEventsCollectionView { return CGSize(width: UIScreen.main.bounds.width - 40, height: 180) } else { return CGSize(width: 150, height: 200) } } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if collectionView == mainEventsCollectionView { return 3 } else { return 7 } } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView == mainEventsCollectionView { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainEventsCell", for: indexPath) as! MainEventCollectionViewCell cell.eventTitle.text = "Hello world".uppercased() cell.setupCell() return cell } else { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "importantEventsCell", for: indexPath) as! ImportantEventsCollectionViewCell print(indexPath.row) cell.setupCell() return cell } }
Cell:
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.roundCorners(.allCorners, radius: 6, borderColor: .clear, borderWidth: 0) } func setupCell() { self.content.backgroundColor = colorWithAlpha(.black, alpha: 0.7) self.eventDate.textColor = .white self.eventTime.textColor = .white self.eventName.textColor = .white if self.content.layer.sublayers!.count > 3 { self.content.layer.sublayers!.removeLast() } if self.eventDate.text == "Today" { self.content.backgroundColor = .clear DispatchQueue.main.async(execute: { self.content.drawGradient(colors: [UIColor(red: 250/255, green: 217/255, blue: 97/255, alpha: 0.7).cgColor, UIColor(red: 255/255, green: 135/255, blue: 67/255, alpha: 0.7).cgColor], locations: [0, 1]) }) self.eventDate.textColor = .black self.eventTime.textColor = .black self.eventName.textColor = .black } }
原文:https://stackoverflow.com/questions/39722070
最满意答案
GCC将显式删除具有控制它们的常量表达式的条件块,并且GNU编码标准明确建议您利用这一点 ,而不是使用诸如依赖预处理器之类的粗糙方法。 虽然使用预处理器
#if
可能看起来更有效,因为它在早期阶段删除了代码,但实际上,现代优化器在为您提供尽可能多的信息时效果最好(当然,如果您可以避免添加,它会使您的程序更清晰,更一致在不必要的点处的相分离依赖性)。像这样的决策对于现代编译器来说非常非常容易 - 即使非常简单的TCC也会执行一些死代码消除; 像LLVM和GCC这样的强大系统会发现这一点,以及作为人类读者可能错过的更复杂的情况(通过跟踪变量的生命周期和修改,而不仅仅是单点查看)。
这是完全编译的其他优点之外,例如
if
中的代码将被检查错误(而#if
对于删除当前系统中错误的代码更有用,例如对不存在的平台函数的引用)。GCC will explicitly remove conditional blocks that have a constant expression controlling them, and the GNU coding standards explicitly recommend that you take advantage of this, instead of using cruder methods such as relying on the preprocessor. Although using preprocessor
#if
may seem more efficient because it removes code at an earlier stage, in practice modern optimizers work best when you give them as much information as possible (and of course it makes your program cleaner and more consistent if you can avoid adding a phase-separation dependency at a point where it isn't necessary).Decisions like this are very, very easy for a modern compiler to make - even the very simplistic TCC will perform some amount of dead-code elimination; powerful systems like LLVM and GCC will spot this, and also much more complex cases that you, as a human reader, might miss (by tracing the lifetime and modification of variables beyond simply looking at single points).
This is in addition to other advantages of full compilation, like the fact that your code within the
if
will be checked for errors (whereas#if
is more useful for removing code that would be erroneous on your current system, like references to nonexistent platform functions).
相关问答
更多-
如果在调试配置中编译,则C ++ hash_map.clear()很慢(C++ hash_map.clear() is slow if compiled in debug configuration)[2023-10-18]
TL; DR: std::hash_map不是正确的工具。 这是MSVC多年前弃用的非标准扩展 。 阅读std::unordered_map ,它应该符合您的一般性能要求。 另外,看到这个 。 在撰写本文时,我正在使用VS 2017 15.3.5,因此我的std库标题副本是合理的最新版本。 我不再拥有VS 2010头文件的副本,因此我的答案可能不完全适用于您的版本。 如果可能,你应该真的升级。 首先让我们分析一下hash_map.clear() : void clear() _NOEXCEPT { ... -
程序在3个主要的C ++编译器中编译不同。(Program being compiled differently in 3 major C++ compilers. Which one is right?)[2021-10-06]
GCC是正确的,至少根据C ++ 11查找规则。 3.4.3.1 [class.qual] / 2指定,如果嵌套名称说明符与类名相同,则引用构造函数而不是注入的类名。 举例: B::A ba; // object of type A A::A a; // error, A::A is not a type name struct A::A a2; // object of type A 看起来MSVC将其解释为函数式转换表达式,创建一个临时C其中y作为构造函 ... -
rename()不能在使用Dev C ++编译的C程序中工作(rename() not working in a C program compiled using Dev C++)[2023-09-16]
我认为你有一些用rename变量,这就是为什么编译器给called object 'rename' is not a function 。 检查一下 。 如评论中所述,请提供有关您的代码的更多信息。 I think you have some variables named with rename, that's why compiler gives called object 'rename' is not a function. Check this one. As said in the commen ... -
当你想使用多核时,你必须实现一个多线程程序。 那里有很多线程库。 我建议您查看一下OpenMP网站 ,该网站很容易整合并用于并行化。 编辑:一个简单的例子: 通常情况下,您可以简单地通过添加for parallel来并行化for循环: #pragma omp parallel for(...) 当然,您必须链接到OpenMP并使用OpenMP支持进行编译。 You have to implement a multithreaded program when you want to use multiple ...
-
如何在android中查看本机编译的C程序的堆栈跟踪?(How can I view the stack traces of a native compiled C program in android?)[2023-03-13]
尝试在远程模式下使用gdb: https : //source.android.com/devices/tech/debug/gdb可能它已经可以使用了(过去有问题)。 您也可以尝试使用Google Breakpad: https : //github.com/google/breakpad/blob/master/README.ANDROID它有时会运行:) Try to use gdb in remote mode: https://source.android.com/devices/tech/deb ... -
如果在c程序中编译0(if 0 is compiled in c program)[2024-01-01]
GCC将显式删除具有控制它们的常量表达式的条件块,并且GNU编码标准明确建议您利用这一点 ,而不是使用诸如依赖预处理器之类的粗糙方法。 虽然使用预处理器#if可能看起来更有效,因为它在早期阶段删除了代码,但实际上,现代优化器在为您提供尽可能多的信息时效果最好(当然,如果您可以避免添加,它会使您的程序更清晰,更一致在不必要的点处的相分离依赖性)。 像这样的决策对于现代编译器来说非常非常容易 - 即使非常简单的TCC也会执行一些死代码消除; 像LLVM和GCC这样的强大系统会发现这一点,以及作为人类读者可能错过 ... -
您不必修改任何标头。 有必要用extern C {}包装所有C声明。 您可以在cpp文件中执行此操作: extern "C" { #include "some_c_header.h" } int main() { std::cout << "This is C++ code\n"; } 创建一个只包含带C链接的C头的头文件可能很有用: // c_header.hpp #pragma once #ifdef __cplusplus extern "C" { #endif #include " ...
-
char *comet,*group; int a,b; scanf("%s",comet); comet指针是未初始化的。 您需要分配内存并在此分配的内存中生成comet点,否则scanf将在随机位置写入字节,这可能会使系统崩溃。 char *comet,*group; int a,b; scanf("%s",comet); comet pointer is uninitialized. You need to allocate memory and makes comet points at thi ...
-
解释中有两个含义: 8086内存地址段 对象模块程序部分段 第一个与加载到80386+段寄存器中的内容有关; 它包含一个物理内存起始地址,内存分配长度,允许的读/写/执行访问,以及它是从低到高增长还是反之亦然(加上一些更模糊的标志,比如“复制引用”)。 第二个含义是对象模块语言的一部分。 基本上,有一个名为code的段,一个名为data的段(包含初始化数据),以及一个名为bss未初始化数据段(以20世纪60年代汇编程序的伪指令命名,意思是用符号开始块 )。 当链接器组合对象模块时,它将所有代码段排列在一起, ...
-
你忘了makefile中的-c选项: . . . wordstat.o: wordstat.c $(COMPILER) $(CCFLAGS) -c wordstat.c ↑ - important! 否则此行不会生成目标文件,而是生成可执行的elf文件(a.out),因此可能会导致意外行为,因为您将其重新编译为wordstat(并且已经编译)。 You forgot the -c option in the makefile: . ...