无干扰的学生

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无干扰的学生相关的知识,希望对你有一定的参考价值。

参考技术A https://www.cityscapes-dataset.com/benchmarks/#scene-labeling-task

https://arxiv.org/abs/2005.10266

作者网页  http://www.liangchiehchen.com/    作者是DeepLab的一作,MobileNetV2、MobileNetV3的作者

https://blog.csdn.net/m0_47645778/article/details/106391052

无干扰的学生

摘要: 大型判别模型的有监督学习是现代计算机视觉的重要组成,其依赖于大规模的人工标注,以获得最先进水平。反过来,监督学习是否有效受限于人工标注数据的规模。对语义分割来说,因为标注成本特别高,这一限制就更为显著。但是可能会有大量的未标注数据可以使用。本文,我们尝试用半监督学习在未标注的视频序列和额外的图像中提高Cityscapes分割的性能,同时处理语义分割、实例分割和全景分割。本文避免构建特定于标签传播的复杂的、可学习框架(例如,patch匹配和光流)。相反,我们只在未标注数据上预测伪标签,并使用人工标注和伪标签数据训练后续模型。该过程被迭代好几次。结果,我们的无干扰学生模型,通过这种简单有效的迭代半监督学习,在Cityscapes的3个基准上达到最先进水平,在测试集上达到了67.8%的PQ、42.6%的AP和85.2%的mIOU。我们认为本项工作是朝着一个流程简单、利用未标注视频序列和额外图像、在核心计算机视觉任务上超越最先进水平的值得注意的一步。

关键词: 半监督学习,伪标签,语义分割,实例分割,全景分割

1引言

本项工作利用未标注的视频帧和额外的未标注图像,从语义分割、实例分割和全景分割三个方面对城市场景分割进行改进。重要的是,我们没有使用任何方法来跨帧传播标签,例如光流[54,23,56]、补丁匹配[4,6]或可学习的运动向量[95]。相反,我们提出使用一个简单的迭代半监督学习过程。每一次迭代中,前一次迭代的模型为未标注的视频帧生成伪标签,见图1。具体地说,对每个未标注视频帧用蒸馏(即测试数据增强)生成伪标签,测试数据增强也就是对待标注的视频帧使用多个增强(多尺度输入,左右翻转)。用原始的标注数据和新生成的伪标签数据进行后续的迭代训练。我们用这样一种简单有效的训练方式,在Cityscapes分割上取得最先进水平,在测试集上达到了67.8%的PQ、42.6%的AP和85.2%的mIOU。我们希望这种迭代半监督学习可以为语义分割提供更 label-efficient 方法。

2.相关工作

我们的方法既涉及自训练[71,88,67,20,25,91],也涉及半监督学习[68,44,57,64,86]。自训练是指一个模型在未标注数据上生成的标签被用来训练下一个模型。半监督是指使用一些人工标注的数据来引导使用无标注数据的训练过程。具体地,我们的模型训练使用了一些人工标注数据和大量的伪标注[42,72,34,3]视频帧。

半监督学习已广泛应用于多种计算机视觉任务,包括语义分割[57,19,59,31,80,35,81,73,96]、目标检测[68,76,64]、实例分割[35,60]、全景分割[45]、人体姿势估计[58]、人物再识别[93]、多目标跟踪与分割[77,62],等等。

我们提出的迭代半监督学习与[57]、STC[80]、Simple-Does-It[35]、[45]以及受干扰的学生[84]相似。特别的,我们的迭代半监督学习类似于[57]的期望最大化方法,它在估计伪标签和利用弱标注优化模型(边界框或图像级标注)之间轮流交替。类似地,[45]利用标注数据和弱标注数据(“thing”类的边界框和“stuff”类的图像级标注)为全景分割生成伪标签。和这两个工作不同,我们没有使用任何弱标注数据。此外,我们不按标注的难度对图像进行分类,也不使用其它的辅助,例如STC[80]中的显著性图。Simple-Does-It使用复杂的过程来清洗伪标签,而我们只是简单地使用神经网络的输出。最后,和受干扰的学生[84]一样,我们在后续迭代中使用更大的学生网络,但是没有使用任何的加噪声的数据增强,例如RandAugment[18]。

在生成伪标签时,我们使用了一种简单的测试数据增强(test-time augmentation),例如多尺度输入和左右翻转,这是在语义分割中常用的[12,92],和数据蒸馏[64]相似。我们的方法是一种迭代的过程,我们利用了未标注的视频帧进行场景分割,同时处理语义分割、实例分割和全景分割。我们不设置阈值来清洗假阳预测,以避免调节另一个超参数。

3 方法

算法1是我们提出的用于场景分割的迭代半监督学习流程。假设有两组图像,一种有人工标注的,另一组没有。人工标注数据是用来训练教师网络的。未标注数据的伪标签是由教师网络生成,生成的时候使用测试数据增强。然后用这些伪标注数据、用相同的损失函数训练学生网络。学生网络在验证集或测试集评估之前,要用人工标注数据微调学生网络。最后,用学生网络作为新的教师网络,开始新一轮的过程迭代。我们的方法称为无干扰的学生,由受干扰学生[84]的启发,我们在后续迭代中使用更大的学生网络,但是没有对学生网络加噪声,例如RandAugment[18]。我们算法如图2所示,我们将详细阐述细节。

算法1    用于城市场景分割的迭代半监督学习

标注数据: 对图像 和对应的人工标注

未标注数据: 张未标注的图像

步骤1: 在人工标注的数据上训练教师网络 (推理函数记为 ),最小化场景分割的损失函数 :

在我们的任务中,

步骤2: 在未标注数据上使用测试数据增强(多尺度输入和左右翻转)生成伪标签 :

其中 表示测试数据增强

步骤3: 以同样的损失函数在伪标签数据 上训练一个更大或相等的学生网络 :

步骤4: 在人工标注数据 上使用相同的损失函数微调步骤3的学生网络 :

步骤5: 回到步骤2,将学生网络 作为新的教师网络,迭代此过程直到预期的迭代次数。

场景分割的损失函数:     我们的核心模块是最先进的自底向上的全景分割模型,Panoptic-DeepLabv3+[14],它是通过增加一个与类无关的实例分割分支来改进语义分割模型DeepLabv3+[13]。它的实例分割分支包括一个简单的实例中心预测模块,也就是对每个像素到其对应中心的偏移量的回归。因此,场景分割的损失函数 包括3个部分,语义分割的softmax交叉熵 ,实例中心预测的均方差损失 ,以及偏移量回归的L1损失 。在我们的算法中,教师网络和学生网络使用相同的总损失函数 。

伪标签生成:     用所有的人工标注数据(以及第一次迭代后所有的伪标注数据)训练完教师网络后,我们为所有的未标注数据生成(或更新)伪标签,并且使用测试数据增强 ,例如多尺度输入和左右翻转。在处理大分辨率图像时(例如Cityscapes的1024×2048),为节省磁盘空间,我们生成硬伪标签(即独热分布)。

伪标签中的此在车区域(ego-car):     Citysapes的图像都是在一个行驶的车辆里拍摄的。因此在视频的所有帧里都可以看到拍摄者所在的汽车的一部分,称为此在车区域。在对模型进行评估时,这部分区域是被忽略的。然而,我们发现,在对模型进行训练时,给这些区域指定随机标签值会混淆模型。为了解决该问题,我们采用一种简单解决方案:我们知道,Citysapes的所有图像都经过了很好的标定,在同一个视频中,此在车区域都是在相同的位置。由于我们可以在每30帧中找到一张有人工标注的视频帧,我们可以将该帧上的此在车的区域信息传播到其它29帧上,并为其分配空标签(也就是在这些区域上没有损失函数的反向传播)。

用于场景分割的更强主干网络:     在我们的算法中,教师网络在第一次迭代时用的是高效的主干网络Xception-71(X-71)[16,63,13]。下一次迭代中,应该使用更强的主干网络,这样生成的伪标签质量更好。本项工作中,我们修改了强大的Wide ResNet-38(WR-38)[83,90]用于场景分割。具体的修改是,将WR-38[83]的最后个残差块B7去掉,并将残差块B6再重复两次,得到我们提出的WR-41。另外,在最后3个残差块(unit rate是1、2、4,和[12]一样)中,我们使用drop path[32,50],drop out的保留率是常数0.8,我们还使用multi-grid scheme [12,79]。结果表明,全监督学习中,WR-41比X-71性能更好。

4 实验

我们在Cityscapes数据集[17]上执行实验,其包含大量不同的来自德国50个城市的街景视频。在这些视频帧中,有5000张图像有高质量的像素级标注,训练集、验证集、测试集分别是2975、500和1525张。每张图片都是在一个30帧的视频片段里的第20帧。此外,该数据集还有20000张粗标注数据。我们将数据集划分如下:

train-fine: 精细标注的训练集,2975张

val-fine: 精细标注的验证集,500张

test-fine: 测试集,1525张,其精细标注没有公开,评估是在服务器上进行的

train-extra: 额外的20000张粗标注数据。我们提出的方法不仅仅是用在Cityscapes是视频上,因此我们也为这部分数据生成伪标签,而不是用它自带的粗标签。

train-sequence: 包含train-fine中图像的视频片段集合,有2975×30=89250张图像

val-sequence: 包含val-fine中图像的视频片段集合,有500×30=15000张图像

此外,还可将训练集验证集合并起来,例如,将train-fine与val-fine合并就得到trainval-fine,将train-sequence与val-sequence合并就得到trainval-sequence。

实验设置: 我们用mIoU、平均精确度(AP)和全景质量(PQ)分别评估语义分割、实例分割和全景分割的结果。

我们使用最先进的自底向上的Panoptic-DeepLab[15]全景分割模型。Panoptic-DeepLab是个简单的框架,可同时生成语义分割、实例分割和全景分割的结果,而不需要在各个任务上微调。当使用Panoptic-DeepLab时,我们遵循和[15]相同的训练设置。例如,我们的模型是在32块TPU上用Tensorflow训练的。我们使用poly学习率调整方案,当主干为Xception-71(X-71)时,初始学习率设为0.001,当主干为WideResNet-41(WR-41)时,学习率设为0.0001。训练期间,对批量归一化进行了微调,使用了随机缩放的数据增强,使用了不带权重衰减的Adam优化器。Cityscapes上,训练时的图像裁剪尺寸是1025×2049,批量大小是32,180K个training iterations。和其它的全景分割工作[38,43,37,85,61,87,78]相似,我们将那些分割区域面积小于4096的stuff重新分配为空标签。另外,我们使用了多尺度推理和左右翻转,来进一步提升在测试集服务器上的性能,多尺度包括0.5、0.75、1、1.25、1.5、1.75、2。

4.1 城市场景分割结果

Cityscapes val-fine set:     在半监督的每次迭代中,为了让教师网络生成更好的伪标签,所有的数据子集,包括Mapillary Vistas[55]和Cityscapes trainval fine,以及在第一次迭代后会用的trainval-sequence和train-extra,都被利用。而学生网络则永远是用在Mapillary Vistas预训练的模型来初始化(除非特别说明它要被先前的迭代中模型初始化)。表1是验证集结果。在第0次迭代中,使用最先进的Panoptic-DeepLab,以Xception-71为主干,作为教师网络在train-sequence和train-extra生成伪标签,来自[15]的方法在验证集上的结果也列在表中方便比较,生成了伪标签的数据在后续迭代中用来训练学生网络,学生网络是用所提的WideResNet-41为主干网络。在第1次迭代中,我们将Panoptic-DeepLab(-X71)的基线提升了3.8%PQ、3.1%AP、3.2%mIOU。然后将学生网络作为新的教师网络,在所有可得的数据集上微调,也就是trainval-sequence,train-extra和trainval-fine。在第2次迭代中,因为是用质量更好的伪标签训练,在新的学生网络上有进一步的1.3%PQ、1.5%AP和0.8%mIoU的提升。此外,如果用第1次迭代的结果初始化学生网络,还可以进一步提高性能,如表中最后一行所示。

Cityscapes test-fine set: 表2是在Cityscapes测试集的结果。如表所示,我们的单一模型同时在Cityscapes的3个基准中排名第一。

生成的伪标签可视化:     我们观察到在第1次迭代和第2次迭代之间微小的差异,两者的教师模型都能生成高质量的伪标签。为了进一步地查看两者的细微差别,我们在图3中放大看一些生成的伪标签。如图3所示,在细长或小物体上,第2次迭代教师网络生成的伪标签要稍好些。

分割结果的可视化:     图4是学生网络在val-fine set上分割结果的可视化。

4.2 消冗研究

本节对一些设计选择进行消冗研究。除非有特别说明,主干网络是Xception-71。

训练迭代次数:     首先我们验证性能的提升不仅仅来自于训练迭代次数的延长(笔者注,迭代在本文有两种不同的意思,一种是半监督迭代,即教师-学生框架中用学生作为新的教师,迭代2次,另一种是训练iterations,迭代180K次),而是来自于超大规模的伪标签图像。我们用Panoptic-DeepLab[15]训练60K次迭代,在Citysacapes的train-fine上达到62.9%的PQ,将迭代次数增加到120K,性能没有任何的提升(62.7%PQ),也就是说后60K次训练已经饱和。相比之下,我们提出的无干扰学生训练使用更大规模的train-sequence数据,用180K次迭代可以获得更好的性能(65.3%PQ)。

用于生成伪标签的教师网络的设计选择:     生成伪标签时,要考虑4点因素:(1)将空标签分配给此在车区域,(2)使用测试数据增强,(3)在Cityscapes人工标注数据微调,(4)Mapillary Vistas数据的预训练。将此在车标注为空标签,带来0.7%的PQ,0.5%的AP和0.4%的mIOU的提升。我们认为,在生成伪标签的时候,给此在车区域分配错误的标签会轻微地影响模型的训练。不使用测试数据增强(即多尺度输入和左右翻转)生成伪标签,性能下降了0.8%PQ、1.1%AP和0.9%mIOU。不使用Cityscapes人工标注数据微调,性能下降1.4%PQ,1.2%AP和1.3%mIOU。最后,如果教师网络没有在Mapillary Vistas数据集上预训练,性能下降2.2%PQ、2.2%AP和1.5%mIOU。

训练学生网络的设计选择:     表4是用不同的数据训练学生网络的结果。在Cityscapes train-fine上训练的学生网络作为基线,性能为63.1%PQ,35.2%AP,80.1%mIoU。使用带伪标签的train-sequence数据,性能提升2.2%PQ、2.4%AP和2.1%mIoU。将人工标注的train-fine数据和带有伪标签的train-sequence数据混合,会导致性能轻微地下降,我们认为这是人工标注和伪标签的不一致缘故,因为train-fine是train-sequence的子集。最后,使用更多的伪标签(train-sequence和train-extra)可将结果提升至66.9%PQ,40.2%AP和84.2%mIoU。

人工标注图像数量变化而伪标签图像数量不变:     图5中,我们研究了半监督学习中人工标注数据和伪标注数据的不同配比的影响。人工标注数据的数量是不同的,而伪标注数据的数量是固定的。具体地,教师网络只在不同数量的Cityscapes train-fine图像上训练,也就是不使用其它的人工标注数据例如Mapillary Vistas。在train-sequence和train-extra上生成的伪标签用来训练另一个学生网络。教师网络和学生网络都使用Xception-71作为主干。为了对比,我们还报告了人工标注数据数量相同情况下的有监督学习的性能。在图中,我们观察到,(1)随着使用更多人工标注图像,半监督学习的性能在3个指标(PQ、AP和mIOU)上都能一致地优于监督学习,(2)使用40%人工标注数据的半监督学习的性能可达到使用100%人工标注数据的监督学习的性能的98.9%,97.2%,98.6%(分别对应PQ,AP和mIoU),即图中灰色虚线所示,(3)当使用100%的人工标注数据的半监督学习可以达到65.2%PQ,38.6%AP,82%mIoU,和使用[15]的在Mapillary Vistas预训练模型的监督学习的性能是有可比性的(65.3%PQ,38.8%AP,82.5%mIoU)。

人工标注图像数量不变而伪标签图像数量变化:     教师网络在不同数量的伪标签数据。结果如图6所示,我们观察到在3个指标上伪标签数据越多,性能就越好。

训练方法:     表5中我们比较了不同的训练方法:监督,半监督,迭代半监督。我们使用我们最强大的主干网络WR-41,试图突破性能的极限。我们观察到半监督学习比监督学习有显著改善,分别提高了5.1%PQ和4.4%AP和5.2%mIOU,主要是因为Cityscapes人工标注数据集规模小的缘故。使用迭代半监督,性能进一步提升至1.3%PQ,1%AP,0.2%mIoU。我们认为这是因为PQ和AP还有很大的提升空间,而mIoU结果趋于饱和,在公共排行榜上也是这样,名列前茅的模型之间的差距大约0.1%。

从Cityscapes到Mapillary Vistas的迁移学习:     先前工作[95,61,15]和我们的工作已经表明,将大规模的Mapillary Vistas数据集训练的模型迁移到Cityscapes上是有效的,因为两者都包含街景图像。我们尝试相反方向的迁移学习,也就是从Cityscapes到Mapillary Vistas的迁移学习,结果如表6所示。基线模型是以WR-41为主干,只在ImageNet[69]上预训练,性能可达到37.1%PQ、16.7%AP和56.2%mIOU。如果我们在原始的Cityscapes的trainval-fine数据集上预训练,性能会轻微地下降。有趣的是,当我们进一步在Cityscapes的伪标注数据上预训练,可以看到在PQ指标上有很小的0.7%的改善。我们认为在Cityscapes上预训练的改善是微小的,主要是因为Cityscapes的图像大多是在德国拍摄的,而Mapillary Vistas的数据更多样。

4.3 修改后的Wide ResNet-38:WR-41

本节我们报告我们修改后的Wide ResNet-38,也就是WR-41在ImageNet和Cityscapes上的结果。

ImageNet-1K val set:     表7是我们在ImageNet-1K验证集上报告结果。如表所示,我们用Tensorflow复现[83]提出的WR-38取得了20.36%的Top-1 Error,比原论文结果稍差一点。可能是深度学习工具库之间存在一些差异。但是请注意,我们关注的分割,ImageNet只是用来预训练。我们提出的WR-41性能稍微更好。使用dropout保留率恒定为0.8的drop path可以提高性能。

Cityscapes val set:     表8中了Panoptic DeepLab[15]以WR-38(我们自己的TensorFlow复现)和WR-41为主干在Cityscapes的验证集上的结果。如表所示,我们可以看到:(1)使用drop path[32](保留率恒定为0.8)能够持续地提高2个主干的性能,(2)使用[12]提出的multi-grid scheme能进一步提升性能,其中WR-38和WR-41的最后两或三个残差块的unit rates设置为(1,2)或(1,2,4),(3)使用WR-41作为主干比使用WR-38作为主干稍有改进,(4)全景分割中,WR-41为主干会稍快(参数稍微地更少),因为最后层加的ASPP是2048通道而不是4096通道。另外,输入尺寸为1025×2049,在GPU(Tesla V100-SXM2)上的推理时间,WR-38是437.9ms,WR-41是396.5ms。

表9中我们报告了使用测试数据增强(也就是多尺度输入和左右翻转)以及在Mapillary Vistas上预训练的影响,以Panoptic DeepLab分割网络,WR-41是其主干。使用Mapillary Vistas和测试数据增强都能一致地提高性能。此外,以WR-41为主干的Panoptic-DeepLab要稍优于以WR-38为主干的Panoptic-DeepLab,这和[15]中的报告是一致的。

Cityscapes test set:     表10中我们报告了使用Panoptic DeepLab[15]和我们改进的WR-41在Cityscapes测试集上的结果。在没有额外数据的情况下,我们的Panoptic DeepLab(WR-41)比Panoptic DeepLab(X-71)的性能提高了1.4%PQ、1.9%AP和2.1%mIOU。使用Mapillary Vistas预训练的情况下,我们的Panoptic DeepLab(WR-41)比DeepLab(X-71)性能要好1.0%PQ,1.6%PQ,0.3%mIoU。

5 结论

本文提出一种迭代半监督学习方法,可以显著的同时提高Cityscapes的语义分割、实例分割和全景分割的性能。这个半监督学习过程能有效利用未标注的视频帧以及未标注的额外图像来提高模型性能,不需要在网络上增加额外的结构和学习模块。也就是说,通过简单的测试数据增强(即多尺度输入和左右翻转)获得的伪标签就足以提高监督学习任务的性能。我们的模型在Cityscapes的3个基准上达到了最先进水平,无需对每个任务分别微调或分别的设计。我们希望我们的简单有效的训练方法能够建立一个基线流程来利用大量的未标注的视频帧和额外图像来完成视觉任务。

笔者注: 这篇论文有一些令人混淆的地方,例如,算法1的步骤4,说明对学生网络的微调是用人工标注数据(trainval-fine),4.1节中提到对学生网络的微调是用到所有可得数据,也就是trainval-sequence,trainval-extra,trainval-fine,相关的表述还出现在4.2节消冗实验里教师网络的设计选择和学生网络的设计选择里

Swift 2 无代表

【中文标题】Swift 2 无代表【英文标题】:Swift 2 Nil Delegate 【发布时间】:2015-12-08 06:15:32 【问题描述】:

所以我想创建一个 IOS 应用程序来生成一组学生,将他们添加到课程中,然后显示学生。我可以在表格视图的列表中显示学生,但现在我想让用户触摸学生的姓名并被带到包含该学生信息的页面(姓名最高等级等)。学生班完美无缺,课程有效,我唯一的问题是我无法让学生从一种观点转向另一种观点。

这是我目前所拥有的:

//
//  DataTableViewController.swift
//  assignment8
//

import Foundation
import UIKit


class DataTableViewController: UITableViewController 

  var delegate:StudentSelectionDelegate! = nil
  var students = [Student]();
  var course = Course();

  // MARK: - UITableViewDataSource

  override func viewDidLoad() 
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

  

  func didSelectStudent(controller:UITableViewController, student:Student!) 

    controller.navigationController?.popViewControllerAnimated(true)

  

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    self.course = courseStorage.getCourse();
    self.students = course.getArrayOfStudentSortedByLastName();
    return course.count;
  


  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
    let row = indexPath.row
    let currentStudent = students[row];
    if (delegate != nil) 
      delegate.didSelectStudent(self,student:currentStudent)
    
    else 
      print ("delegate is nil :(");
    
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
  

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("studentCell", forIndexPath: indexPath)

    cell.textLabel?.text = students[indexPath.row].lastName + ", " +
      students[indexPath.row].firstName;
    return cell
  

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    print("ping");
    if segue.identifier == "studentSegue" 
      let nextScene =  segue.destinationViewController as! studentViewController
      // Pass the selected object to the new view controller.
      if let indexPath = self.tableView.indexPathForSelectedRow 
        let selectedStudent = students[indexPath.row]
        print (selectedStudent.firstName);
        nextScene.student = selectedStudent;
      
    
  

//
//  DataViewController.swift
//  assignment8
//

import UIKit



class DataViewController: UIViewController 

  @IBOutlet weak var dataLabel: UILabel!
  var dataObject: String = ""
  let tableData = ["One","Two","Three"];



  override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
  

  override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  

  override func viewWillAppear(animated: Bool) 
    super.viewWillAppear(animated)
    self.dataLabel!.text = dataObject
  

  func tableView(tableView: UITableView!, numberOfRowsInSection section: Int)
    -> Int 
    return self.tableData.count;
  

//
//  studentViewController.swift
//  assignment8
//

import UIKit

protocol StudentSelectionDelegate 
  func didSelectStudent(controller: UITableViewController, student:Student)


class studentViewController: UIViewController 

  var delegate = StudentSelectionDelegate.self;

  var name = String();
  var student = Student();


  @IBOutlet weak var StudentName: UILabel!
  override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  

  func didSelectStudent(controller:UITableViewController, student:Student!) 
    student.description;
    print ("pong")
    StudentName.text = student.firstName + " " + student.lastName;

    controller.navigationController?.popViewControllerAnimated(true);
  

  override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  
  //  override func viewWillAppear(animated: Bool) 
  //    StudentName.text = name
  //  


到目前为止,这是我的故事板。

所以,每当我尝试点击一个学生时,它都会打印出我决定在代理为 nil 时使用的消息。到目前为止,我已经尝试查看关于 SO 的所有其他答案,但没有一个解决了我的问题。

【问题讨论】:

您如何创建从一个视图控制器到另一个视图控制器的转场?您喜欢表格视图中的转场吗?我认为在内部调用 tableview.didselectrowatindexpath 不是一个好主意,也许你想做的是 performeguewithidentifier? 这是我遵循的几个教程中的做法,例如这里。 makeapppie.com/2015/02/17/… 【参考方案1】:

为了能够将信息从一个视图控制器发送到另一个视图控制器,您应该使用 segues。根据图像,这似乎就是您正在做的事情。如果你不知道如何使用 segue,你可以在这里找到一个很好的答案:Sending data with Segue with Swift

使用 segues,您将能够设置下一个视图控制器的委托:

protocol MyDelegate 
     func myFunction()


class FirstViewController: UIViewController, MyDelegate 

    func myFunction() 
        // do what the function does
    

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        if let secondVC = segue.destinationViewController as? SecondViewController 
            secondVC.delegate = self
        
    



class SecondViewController: UIViewController 
    var delegate: MyDelegate!

在你转入第二个视图控制器之前(你正在为转场做准备),你将 SecondViewController 的委托变量设置为 self,因为 FirstViewController 符合 MyDelegate 协议,所以它可以在那里使用。现在,在 SecondViewController 中,您可以使用 delegate.myFunction(),它会执行 FirstVC 函数中写入的任何操作,因为 FirstVC 是 SecondVC 的委托。

【讨论】:

感谢您告诉我,委托仅用于从另一个视图发回数据,并且首先需要使用 segues 发送数据!我认为在我的故事板中添加一个转场会使我的代表触发转场,但事实并非如此!现在我根本不需要委托。

以上是关于无干扰的学生的主要内容,如果未能解决你的问题,请参考以下文章

将数据保存到两个表中。 ID 为“无”的学生不存在。也许它被删除了?

shell脚本:随机抽取任意数量的学生且无重复

自适应滤波器(E 题 本科组)--2017 年全国大学生电子设计竞赛试题

C++设计一个学生信息管理系统

简易无接触温度测量与身份识别装置(F 题) --2020 年TI 杯大学生电子设计竞赛

简易无接触温度测量与身份识别装置(F 题) --2020 年TI 杯大学生电子设计竞赛