- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我以前有过使用 C 进行顺序编程的经验,但那是在 80 年代中期。一般来说,我是 OOP、Swift 和多线程编码的新手。我正在编写一个小程序以更好地理解所有 3 个。我能够构建一个功能程序,该程序启动两个线程,每个线程计数为 200,然后重置为 1 并在无限循环中重新开始计数。每个计数器的值都打印到控制台,每个线程都有一个启动和停止按钮,允许我单独控制它们。一切正常,尽管我承认我的代码远非完美(我不完全尊重封装,我有一些应该本地化的全局变量等......我的主要问题是试图将每个线程计数器值输出到标签而不是将它们打印到控制台。当我尝试更改任何标签的内容时,我得到“在隐式展开可选值时意外发现 nil”
当我在按钮功能中使用类似的代码行时,它工作得很好。
这是我的 ViewController.swift 文件的内容:
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//Call Async Task
startProgram()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBOutlet var threadAValueLabel: NSTextField!
@IBOutlet var threadBValueLabel: NSTextField!
@IBAction func threadAStartButton(_ sender: NSButtonCell) {
threadAGoNoGo = 1
self.threadAValueLabel.stringValue = "Start"
}
@IBAction func threadAStopButton(_ sender: NSButton) {
threadAGoNoGo = 0
self.threadAValueLabel.stringValue = "Stop"
}
@IBAction func threadBStartButton(_ sender: NSButton) {
threadBGoNoGo = 1
self.threadBValueLabel.stringValue = "Start"
}
@IBAction func threadBStopButton(_ sender: NSButton) {
threadBGoNoGo = 0
self.threadBValueLabel.stringValue = "Stop"
}
func changethreadALabel(_ message: String) {
self.threadAValueLabel.stringValue = message
}
func changethreadBLabel(_ message: String) {
self.threadBValueLabel.stringValue = message
}
产生错误的代码位于最后两个方法中:
self.threadAValueLabel.stringValue = message
和
self.threadBValueLabel.stringValue = message
虽然以下代码在按钮函数中,但运行完美。
self.threadBValueLabel.stringValue = "Stop"
创建这两个线程的代码如下:
import Foundation
func startProgram(){
let myViewController: ViewController = ViewController (nibName:nil, bundle:nil)
// Start counting through 200 when Thread A start button is pressed and stop when Thread A Stop button is pressed. When reaching 200, go back to 0 and loop forever
DispatchQueue(label: "Start Thread A").async {
while true { // Loop Forever
var stepA:Int = 1
while stepA < 200{
for _ in 1...10000000{} // Delay loop
if threadAGoNoGo == 1{
print("Thread A \(stepA)")
myViewController.changethreadALabel("South \(stepA)") // Update Thread A value display label
stepA += 1
}
}
stepA = 1
}
}
// Start counting through 200 when Thread B start button is pressed and stop when Thread B Stop button is pressed. When reaching 200, go back to 0 and loop forever
DispatchQueue(label: "Start Thread B").async {
while true { // Loop Forever
var stepB:Int = 1
while stepB < 200{
for _ in 1...10000000{} // Delay loop
if threadBGoNoGo == 1{
print("Tread B \(stepB)")
myViewController.changethreadBLabel("South \(stepB)") // Update Thread B value display label
stepB += 1
}
}
stepB = 1
}
}
}
这对你们大多数人来说可能很简单,但我花了四个晚上试图自己弄清楚并搜索这个论坛,但没有成功。
新编辑:
感谢 Rob 的回答,我得以取得进展,但我遇到了另一个障碍。如果我将我的代码移动到 ViewController 类,我似乎能够访问我的 stringValue 变量 self.threadAValueLabel.stringValue 和 self.threadBValueLabel.stringValue,但下面的行生成“NSControl.stringValue 必须仅从主线程使用”错误信息:
self.threadAValueLabel.stringValue = message
self.threadBValueLabel.stringValue = message
虽然我明白错误消息的含义,但我已经尝试了几个小时来寻找解决此问题的方法,但似乎没有任何效果。
完整代码如下
import Foundation
import Cocoa
public var threadAGoNoGo:Int = 0
public var threadBGoNoGo:Int = 0
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//Call Async Task
// Start counting through 200 when Thread A start button is pressed and stop when Thread A Stop button is pressed. When reaching 200, go back to 0 and loop forever
DispatchQueue(label: "Start Thread A").async {
while true { // Loop Forever
var stepA:Int = 1
while stepA < 200{
for _ in 1...10000000{} // Delay loop
if threadAGoNoGo == 1{
print("Thread A \(stepA)")
self.changethreadALabel("Thread A \(stepA)")
stepA += 1
}
}
stepA = 1
}
}
// Start counting through 200 when Thread B start button is pressed and stop when Thread B Stop button is pressed. When reaching 200, go back to 0 and loop forever
DispatchQueue(label: "Start Thread B").async {
while true { // Loop Forever
var stepB:Int = 1
while stepB < 200{
for _ in 1...10000000{} // Delay loop
if threadBGoNoGo == 1{
print("Tread B \(stepB)")
self.changethreadBLabel("Thread B \(stepB)")
stepB += 1
}
}
stepB = 1
}
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBOutlet var threadAValueLabel: NSTextField!
@IBOutlet var threadBValueLabel: NSTextField!
@IBAction func threadAStartButton(_ sender: NSButtonCell) {
threadAGoNoGo = 1
self.threadAValueLabel.stringValue = "Start"
}
@IBAction func threadAStopButton(_ sender: NSButton) {
threadAGoNoGo = 0
self.threadAValueLabel.stringValue = "Stop"
}
@IBAction func threadBStartButton(_ sender: NSButton) {
threadBGoNoGo = 1
self.threadBValueLabel.stringValue = "Start"
}
@IBAction func threadBStopButton(_ sender: NSButton) {
threadBGoNoGo = 0
self.threadBValueLabel.stringValue = "Stop"
}
func changethreadALabel(_ message:String) {
self.threadAValueLabel.stringValue = message
}
func changethreadBLabel(_ message: String) {
self.threadBValueLabel.stringValue = message
}
}
最佳答案
您的 startProgram
正在实例化一个新的、重复的 View Controller 实例,它没有连接任何 socket 。因此,导出将为 nil
并且尝试引用它们将产生您描述的错误。
如果你真的想让它成为一个全局函数,那么传递 View Controller 引用,例如:
func startProgram(on viewController: ViewController) {
// var myViewController = ...
// now use the `viewController` parameter rather than the `myViewController` local var
...
}
然后 View Controller 可以传递对自身的引用,以便全局 startProgram
知道要更新哪个 View Controller 实例:
startProgram(on: self)
或者,更好的是,(a) 你根本不应该有全局方法; (b) 即使你这样做了,无论如何, View Controller 之外的任何东西都不应该更新 View Controller 的 socket 。这里的简单解决方案是,让 startProgram
成为 ViewController
类的方法,然后您就可以直接引用 outlets。
您已经按照上面的建议编辑了您的问题,将 startProgram
放入 View Controller 类中。然后您遇到了第二个不同的问题,调试器在其中报告:
NSControl.stringValue must be used from main thread only
是的,如果您从后台线程启动 UI 更新,则必须将该更新分派(dispatch)回主线程,例如:
DispatchQueue.main.async {
self.changethreadALabel("Thread A \(stepA)")
}
参见 Main Thread Checker获取更多信息。
关于swift - 尝试更改 NSTextField 的值时得到 "Unexpectedly found nil while implicitly unwrapping an Optional value",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56999788/
在 C# 及其同类语言中,我们总是使用 public string SomeString { get; set;} 但是你也可以使用(我最近才发现这个,而且是在和编译器闲逛的时候发现的) public
我已经为 Controller 中的函数编写了 Swagger 注释,但在生成 swagger-ui 代码时出现错误。以下是我的注释代码 /*** End of Annotation For dele
我正在 PHP 中开发一项服务,该服务使用 exec 函数调用 jar 文件,如下所示: $text = "string with accents á, ó, ú or العربية"; exec(
我正在尝试了解有关在程序中利用/防止缓冲区溢出的方法的更多信息。我知道如果大小是恒定的,下面的代码很容易受到攻击,但是如果大小每次都是随机的怎么办?是否还有办法从堆栈中获取它并以某种方式动态改变溢出字
对于一项学校作业,我应该制作一个可以以小时、分钟和秒为单位存储时间的时间类。一切正常,但仅声明 get 时属性总是返回 0;并设置; private int seconds, minutes, hou
我正在遍历一些测验对象并将结果存储到json变量中。出现"ReferenceError is not defined"错误,不确定原因。 JS代码 // This function will send
使用 Nifi 的 PutDatabaseRecord 处理器在 MySQL 中插入阿拉伯字符(非拉丁语)时,字符被“??????”替换 插入后,阿拉伯字符串被替换为??????。我已经使用 utf8
谁能告诉我为什么 gets(abc) 使用 char[] 而不是使用 int? int abc; char name[] = "lolrofl"; printf("Hello %s.\n",na
为什么在使用 as.POSIXct 转换下面的时间戳时得到所有 NA? > head(tmp$timestamp_utc) [1] Fri Jul 03 00:15:00 EDT 2015 Fri J
def get_submultiples(n): # Get all submultiples of n if n == 1: return [1] i = 2
有没有办法访问基本模型的实际 child ,意思是:继续使用 django Docs 中的示例,让我们假设我正在建模不同的外卖餐厅,它们只是有共同点 姓名 都有deliver方法 至此: class
我正在寻找一个范围的总和,但我总是得到“未定义”。我相信有些东西出现在错误的位置,但我不确定它是什么。 第 1 部分:“编写一个范围函数,它接受两个参数(start 和 end),并返回一个包含从 s
我已将 spring 版本从 4.2.3 更新到 5.0.2,并将安全性从 5.0.1 更新到 5.0.10 并使用 spring -flex版本1.6.0.RC1。 像这样使用 BlazeDS 依赖
我可以输入但在输出中,我得到的结果为零。我使用两门类(class),一门是主要的,是日志,另一门是成绩计算。在成绩计算器中,我编写了方法和构造函数,在日志中,类通过构造函数调用这些方法。 import
我在使用 go 时遇到了构建问题。我想知道这是编译器中的错误还是代码的问题。 // removed the error handling for sake of clarity file, _ :=
我的角色在与盒子互动时出现问题。我有一个 GameObject Player 附加了一个脚本来与游戏中的盒子交互,脚本是: using UnityEngine; using System.Collec
有谁知道为什么我不能在下面生成百分比 codeIshere (第 97-117 行)? var format=d3.format(".1%"); var percent = format(functi
我正在尝试编写图像识别代码,以针对不同动物图像训练系统,这就是代码。我使用 anaconda 作为解释器,使用pycharm作为环境。 import tensorflow as tf import o
我正在尝试在 Java 中初始化 Matcher,但无论字符串是否已初始化且不为 null,都会继续获取 NPE。 这是代码: pattern.compile("\\s"); System.out.p
所以我有这段代码: ; (function (g) { var d = document, i, am = d.createElement('script'), h = d.head || d.g
我是一名优秀的程序员,十分优秀!