我有一个ViewController(oneUserDetailsViewController
),我想用它来控制UIView(weeklyLog
)。为了使UIView工作,我需要将两个NSArray(morningRecord
和nighttimeRecord
)中的数据从ViewController传递到UIView。
我在UIView中设置了一个协议(WeeklyLogDataSource
),其中包含两个函数(morningLogForWeeklyLogView
和nighttimeLogForWeeklyLogView
),用于从委托中返回两个NSArray(在本例中为ViewController) )到UIView。
在UIView中,我已经声明了协议(dataSource
),然后在UIView中创建了代码以访问返回的NSArrays。
在ViewController中,我已将委托添加到类声明中,将委托设置为self,然后实现这两个函数以返回两个NSArray。
据我所知,我已正确设置。但是,当我运行应用程序时,数据不会从View Controller传递到UIView,而是UIView显示默认数据[0, 0, 0, 0, 0, 0, 0]
。使用Print命令,我可以看到UIView中声明的Protocol(dataSource
)显示为nil,我认为这是我问题的根源。但我不知道如何解决它。
你能帮忙吗?
以下是UIView的代码:
import UIKit
// Delegate
protocol WeeklyLogDataSource: class {
func morningLogForWeeklyLogView(sender: weeklyLog) -> NSArray?
func nighttimeLogForWeeklyLogView(sender: weeklyLog) -> NSArray?
}
class weeklyLog: UIView
{
// MARK: Properties
weak var dataSource: WeeklyLogDataSource?
var topRowImages = [UIImageView]()
var secondRowImages = [UIImageView]()
var bottomRowLabels = [UITextView]()
let labelsForTextViews = ["", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
let spacing = 5
let columns = 8
var morningRecord:NSArray! {
didSet {
setNeedsLayout()
setNeedsDisplay()
}
}
var nighttimeRecord:NSArray! {
didSet {
setNeedsLayout()
setNeedsDisplay()
}
}
func setup() {
print("setup in weeklyLog called")
if let morningLog:NSArray = dataSource?.morningLogForWeeklyLogView(self) {
morningRecord = morningLog
} else {
morningRecord = [0, 0, 0, 0, 0, 0, 0]
}
if let nighttimeLog:NSArray = dataSource?.nighttimeLogForWeeklyLogView(self) {
nighttimeRecord = nighttimeLog
} else {
nighttimeRecord = [0, 0, 0, 0, 0, 0, 0]
}
print("morningRecord: \(morningRecord)")
print("nighttimeRecord: \(nighttimeRecord)")
}
// MARK: Initialisation
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.whiteColor()
setup()
setNeedsLayout()
print("dataSource: \(dataSource)")
}
override func layoutSubviews() {
// Set the width and height of each image in proportion to the frame's size.
let imageViewHeight = Int(Double(frame.size.height) * (Double(frame.size.height)/Double(frame.size.width)))
let imageViewWidth = Int(Double(frame.size.width)/Double(columns)) - spacing
var imageViewFrame = CGRect(x: 0, y: 0, width: imageViewWidth, height: imageViewHeight)
// Offset each image's origin by the width of the image.
// top row
for (index, imageView) in topRowImages.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageView.frame = imageViewFrame
}
// second row
for (index, imageView) in secondRowImages.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageViewFrame.origin.y = CGFloat(imageViewHeight)
imageView.frame = imageViewFrame
}
// bottom row
for (index, textView) in bottomRowLabels.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageViewFrame.origin.y = CGFloat(imageViewHeight*2)
textView.frame = imageViewFrame
}
// set images for top row
for var i = 0; i < columns; i++ {
let imageView = UIImageView()
if i == 0 {
imageView.image = UIImage(named: "sun")
} else {
if (morningRecord[i-1] as! NSNumber) == 0 {
imageView.image = UIImage(named: "star_grey")
} else {
imageView.image = UIImage(named: "star_gold")
}
}
topRowImages += [imageView]
addSubview(imageView)
}
// set images for second row
for var i = 0; i < columns; i++ {
let imageView = UIImageView()
if i == 0 {
imageView.image = UIImage(named: "moon")
} else {
if (nighttimeRecord[i-1] as! NSNumber) == 0 {
imageView.image = UIImage(named: "star_grey")
} else {
imageView.image = UIImage(named: "star_gold")
}
}
secondRowImages += [imageView]
addSubview(imageView)
}
// set labels for bottom row
for var i = 0; i < columns; i++ {
let logLabel = UITextView()
logLabel.text = labelsForTextViews[i]
logLabel.textAlignment = .Center
logLabel.textContainer.maximumNumberOfLines = 1;
logLabel.editable = false
logLabel.selectable = false
bottomRowLabels += [logLabel]
addSubview(logLabel)
}
}
override func intrinsicContentSize() -> CGSize {
let superViewHeight = Int(frame.size.height)
let superViewWidth = Int(frame.size.width)
return CGSize(width: superViewWidth, height: superViewHeight)
}
}
以下是ViewController的代码:
import UIKit
class oneUserDetailsViewController: UIViewController, WeeklyLogDataSource
{
@IBOutlet var logView: weeklyLog! { // this is an outlet to the UIView in my Storyboard
didSet {
logView.dataSource = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func morningLogForWeeklyLogView(sender: weeklyLog) -> NSArray? {
let morningLog:NSArray = [0,1,0,1,0,1,0]
return morningLog
}
func nighttimeLogForWeeklyLogView(sender: weeklyLog) -> NSArray? {
let nightLog:NSArray = [0,1,0,1,0,1,0]
return nightLog
}
}
答案 0 :(得分:-1)
谢谢安东。你的答案给了解决方案的种子,我现在已经解决了。
我无法在 UIView 中创建一个调用协议方法的函数(正如我发现的那样, UIView 中无法访问协议方法本身),但我所做的是从 ViewController 调用 UIView 的 setup()函数。最后,我将其放在 didSet {..} 中,而不是将其放在 UIView 的实例中。
首先,调用 setup(),在 UIView 中创建了一个重复的图形版本。第一个是使用默认数组 [0,0,0,0,0,0,0] 绘制的,第二个是使用从 ViewController <传递的数组绘制的/ em>,但它不在屏幕上(不是我想要的)。
要停止我必须删除 UIView 中初始化函数中调用 setup()的代码。此时调用 setup()太早了 - 它导致 UIView 使用默认数组绘制图形。但是当从 ViewController 调用它时, UIView 然后调用委托 ViewController 中的协议方法,从而传递正确的数组 ViewController 到 UIView - 而且,嘿,它已修复。
如果它对任何人都有用,现在就是我的代码:
首先,UIView:
import UIKit
// Delegate
protocol WeeklyLogDataSource: class {
func morningLogForWeeklyLogView(sender: weeklyLog) -> NSArray?
func nighttimeLogForWeeklyLogView(sender: weeklyLog) -> NSArray?
}
class weeklyLog: UIView
{
// MARK: Properties
weak var dataSource: WeeklyLogDataSource?
var topRowImages = [UIImageView]()
var secondRowImages = [UIImageView]()
var bottomRowLabels = [UITextView]()
let labelsForTextViews = ["", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
let spacing = 5
let columns = 8
var morningRecord:NSArray! {
didSet {
setNeedsLayout()
setNeedsDisplay()
}
}
var nighttimeRecord:NSArray! {
didSet {
setNeedsLayout()
setNeedsDisplay()
}
}
func setup() {
print("setup in weeklyLog called")
if let morningLog:NSArray = dataSource?.morningLogForWeeklyLogView(self) {
morningRecord = morningLog
} else {
morningRecord = [0, 0, 0, 0, 0, 0, 0]
}
if let nighttimeLog:NSArray = dataSource?.nighttimeLogForWeeklyLogView(self) {
nighttimeRecord = nighttimeLog
} else {
nighttimeRecord = [0, 0, 0, 0, 0, 0, 0]
}
print("morningRecord: \(morningRecord)")
print("nighttimeRecord: \(nighttimeRecord)")
}
// MARK: Initialisation
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// I removed setup() from here
self.backgroundColor = UIColor.whiteColor()
print("dataSource: \(dataSource)")
}
override func layoutSubviews() {
// Set the width and height of each image in proportion to the frame's size.
let imageViewHeight = Int(Double(frame.size.height) * (Double(frame.size.height)/Double(frame.size.width)))
let imageViewWidth = Int(Double(frame.size.width)/Double(columns)) - spacing
var imageViewFrame = CGRect(x: 0, y: 0, width: imageViewWidth, height: imageViewHeight)
// Offset each image's origin by the width of the image.
// top row
for (index, imageView) in topRowImages.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageView.frame = imageViewFrame
}
// second row
for (index, imageView) in secondRowImages.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageViewFrame.origin.y = CGFloat(imageViewHeight)
imageView.frame = imageViewFrame
}
// bottom row
for (index, textView) in bottomRowLabels.enumerate() {
imageViewFrame.origin.x = CGFloat(index * (imageViewWidth + spacing)) // spacing is set in the Properties section near the top
imageViewFrame.origin.y = CGFloat(imageViewHeight*2)
textView.frame = imageViewFrame
}
// set images for top row
for var i = 0; i < columns; i++ {
let imageView = UIImageView()
if i == 0 {
imageView.image = UIImage(named: "sun")
} else {
if (morningRecord[i-1] as! NSNumber) == 0 {
imageView.image = UIImage(named: "star_grey")
} else {
imageView.image = UIImage(named: "star_gold")
}
}
topRowImages += [imageView]
addSubview(imageView)
}
// set images for second row
for var i = 0; i < columns; i++ {
let imageView = UIImageView()
if i == 0 {
imageView.image = UIImage(named: "moon")
} else {
if (nighttimeRecord[i-1] as! NSNumber) == 0 {
imageView.image = UIImage(named: "star_grey")
} else {
imageView.image = UIImage(named: "star_gold")
}
}
secondRowImages += [imageView]
addSubview(imageView)
}
// set labels for bottom row
for var i = 0; i < columns; i++ {
let logLabel = UITextView()
logLabel.text = labelsForTextViews[i]
logLabel.textAlignment = .Center
logLabel.textContainer.maximumNumberOfLines = 1;
logLabel.editable = false
logLabel.selectable = false
bottomRowLabels += [logLabel]
addSubview(logLabel)
}
}
override func intrinsicContentSize() -> CGSize {
let superViewHeight = Int(frame.size.height)
let superViewWidth = Int(frame.size.width)
return CGSize(width: superViewWidth, height: superViewHeight)
}
}
其次,ViewController:
import UIKit
class oneUserDetailsViewController: UIViewController, WeeklyLogDataSource
{
@IBOutlet var logView: weeklyLog! { // this is an outlet to the UIView in my Storyboard
didSet {
logView.dataSource = self
logView.setup() // this line is the magic!
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func morningLogForWeeklyLogView(sender: weeklyLog) -> NSArray? {
let morningLog:NSArray = [0,1,0,1,0,1,0]
return morningLog
}
func nighttimeLogForWeeklyLogView(sender: weeklyLog) -> NSArray? {
let nightLog:NSArray = [0,1,0,1,0,1,0]
return nightLog
}
}