NSTimer 在 window 关闭后启动、停止和继续
NSTimer starts, stops, and continues after window closes
所以这就是人类逻辑中正在发生的事情(但不应该是)。
- 我的视图控制器加载
- 成功从 Parse 检索我的图像
- 将第一个检索到的图像设置为我的 UIImageView 图像
- 启动我的 5 秒计时器(我认为)
- 然后它什么都不做,只停留在第一张图片上
- 一旦我关闭 window(它由以前的视图控制器以模态方式呈现),我在控制台中看到我的 println() 输出并且我的计时器开始工作。
目标:在我的 UIImageView 中显示一个图像 5 秒左右,然后按顺序显示下一个图像 (imageArray)。
是我的计时器导致了这个功能暂停,还是与我的代码安排方式有关?非常感谢所有 suggestions/help,因为这是一个非常令人沮丧的问题。
这是 Swift 语言,但我可以阅读 Objective-C。
这是我的 class 代码:
//
// ImageDisplayViewController.swift
//
//
// Created by on 5/3/15.
//
//
import Cocoa
import ParseOSX
class ImageDisplayViewController: NSViewController {
@IBOutlet weak var imageView: NSImageView!
var venue: String!
var imageArray = [(Int, NSImage)]()
var image: NSImage!
var timeToDisplay: Int = 0
var timer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
venue = "Bees"
loadImages()
}
var k: Int = 0
func presentNextImage() {
if(k<imageArray.count) {
imageView.image = imageArray[k].1
timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("presentNextImage"), userInfo: nil, repeats: false)
println(timer.timeInterval)
//imageView.image = imageArray[k].1
println("k is \(k)")
k++
println("Just set a new imageView.image")
} else {
println("K is n longer <imageArray.count")
}
}
func loadImages() {
var query = PFQuery(className:groupz)
query.whereKeyExists("imageFile")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) objects.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
let thumbNail = object["imageFile"] as! PFFile
self.image = NSImage(data: thumbNail.getData()!)
let time: AnyObject? = object["displayTime"]
self.timeToDisplay = time!.integerValue
let tempTuple = (self.timeToDisplay, self.image!)
self.imageArray.append(tempTuple)
}
}
println("imageArray.count is: \(self.imageArray.count)")
self.presentNextImage()
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
}
}
将您的 NSTimer
声明为 weak
。来自 NSTimer
上的 Apple docs:
Note in particular that run loops maintain strong references to their
timers, so you don’t have to maintain your own strong reference to a
timer after you have added it to a run loop.
此外,您实际上不需要维护对计时器的引用,因为您没有在选择器参数中调用的方法之外调用 invalidate
,在您的情况下,恰好是分配定时器的方法。
在您的情况下,保持对计时器的弱引用并使其无效以将其从 viewWillDisappear:
中的 运行 循环中移除。
我发现了问题。出于某种原因,将我的视图控制器(显示图像的那个)呈现为 Modal
导致计时器不 运行 或可能被添加到 NSRunLoop。我不太确定。但是,一旦我将 Segue 更改为 Show
,我的计时器就开始正常工作。
感谢 Nikita 的帮助,实际上我从你对我问题的回答中学到了很多东西。
所以这就是人类逻辑中正在发生的事情(但不应该是)。
- 我的视图控制器加载
- 成功从 Parse 检索我的图像
- 将第一个检索到的图像设置为我的 UIImageView 图像
- 启动我的 5 秒计时器(我认为)
- 然后它什么都不做,只停留在第一张图片上
- 一旦我关闭 window(它由以前的视图控制器以模态方式呈现),我在控制台中看到我的 println() 输出并且我的计时器开始工作。
目标:在我的 UIImageView 中显示一个图像 5 秒左右,然后按顺序显示下一个图像 (imageArray)。
是我的计时器导致了这个功能暂停,还是与我的代码安排方式有关?非常感谢所有 suggestions/help,因为这是一个非常令人沮丧的问题。
这是 Swift 语言,但我可以阅读 Objective-C。
这是我的 class 代码:
//
// ImageDisplayViewController.swift
//
//
// Created by on 5/3/15.
//
//
import Cocoa
import ParseOSX
class ImageDisplayViewController: NSViewController {
@IBOutlet weak var imageView: NSImageView!
var venue: String!
var imageArray = [(Int, NSImage)]()
var image: NSImage!
var timeToDisplay: Int = 0
var timer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
venue = "Bees"
loadImages()
}
var k: Int = 0
func presentNextImage() {
if(k<imageArray.count) {
imageView.image = imageArray[k].1
timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("presentNextImage"), userInfo: nil, repeats: false)
println(timer.timeInterval)
//imageView.image = imageArray[k].1
println("k is \(k)")
k++
println("Just set a new imageView.image")
} else {
println("K is n longer <imageArray.count")
}
}
func loadImages() {
var query = PFQuery(className:groupz)
query.whereKeyExists("imageFile")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) objects.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
let thumbNail = object["imageFile"] as! PFFile
self.image = NSImage(data: thumbNail.getData()!)
let time: AnyObject? = object["displayTime"]
self.timeToDisplay = time!.integerValue
let tempTuple = (self.timeToDisplay, self.image!)
self.imageArray.append(tempTuple)
}
}
println("imageArray.count is: \(self.imageArray.count)")
self.presentNextImage()
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
}
}
将您的 NSTimer
声明为 weak
。来自 NSTimer
上的 Apple docs:
Note in particular that run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
此外,您实际上不需要维护对计时器的引用,因为您没有在选择器参数中调用的方法之外调用 invalidate
,在您的情况下,恰好是分配定时器的方法。
在您的情况下,保持对计时器的弱引用并使其无效以将其从 viewWillDisappear:
中的 运行 循环中移除。
我发现了问题。出于某种原因,将我的视图控制器(显示图像的那个)呈现为 Modal
导致计时器不 运行 或可能被添加到 NSRunLoop。我不太确定。但是,一旦我将 Segue 更改为 Show
,我的计时器就开始正常工作。
感谢 Nikita 的帮助,实际上我从你对我问题的回答中学到了很多东西。