为什么我不能使用委托将数据从我的ViewController传递到我的自定义UIView? (迅速)

时间:2016-02-17 00:36:34

标签: ios swift uiview delegates protocols

我有一个ViewController(oneUserDetailsViewController),我想用它来控制UIView(weeklyLog)。为了使UIView工作,我需要将两个NSArray(morningRecordnighttimeRecord)中的数据从ViewController传递到UIView。

我在UIView中设置了一个协议(WeeklyLogDataSource),其中包含两个函数(morningLogForWeeklyLogViewnighttimeLogForWeeklyLogView),用于从委托中返回两个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
  }

}

1 个答案:

答案 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
  }

}