0

I´m stuck on how to display a view from inside a completion block. If I use the same code outside the completion block the view is shown. I´m sure the block is getting executed and I also have setNeedsDisplay in a didSet for an array I use inside the block. So what am I missing?

private var storeViews = [UIView](){ didSet{self.view.setNeedsDisplay()}}

hrd.requestData(from: "somepage.php"){[weak self] (status:Bool,items:[[String:String]]?) in
    if status
    {
        for var i in (0..<items!.count)
        {
            if let item = items?[i]
            {
                var shape = CGRect()
                shape.size = CGSize(width: 50,height: 30)

                let xPosStr = item["xPosition"]
                let yPosStr = item["yPosition"]

                let position = CGPoint(x: (self?.stringToFloat(xPosStr!))!,y: (self?.stringToFloat(yPosStr!))!)

                shape.origin = position
                let someView = UIView()
                someView.frame = shape
                someView.backgroundColor = UIColor.red

                self?.view.addSubview(someView)
                self?.someViews.append(someView)
            }
        }
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
lestat
  • 1
  • 2
  • your question is unclear; what kind of view are you displaying? an array would tend to indicate a tableView in which case you neet to call reloadData from the main que. Post code. – Josh Homann May 10 '17 at 03:23
  • I need the screen to have some squares so I´m using CGRect and besides of showing them I´m storing them in an array, and the array has the didSet with the setNeedsDisplay – lestat May 10 '17 at 03:28
  • Can you add your code that you have so far. – Tristan Beaton May 10 '17 at 03:35
  • How are you drawing these squares? CAShapeLayer, UIView with auto layout, UIView manual frame, UIView.drawRect()? – Josh Homann May 10 '17 at 03:58
  • Hi, I just put the code (the loop doesn´t show complete because of the less than character) – lestat May 10 '17 at 04:08

1 Answers1

0

Firstly, setNeedsDisplay marks the view that it the view needs to be redrawn. This internally calls drawRect. You should call this only if you override drawRect in a UIView subclass with your own custom implementation. I believe you are making an asynchronous API request and you're adding the views inside the completion block. UI updates should be only done on the main thread. You need to add the subview in the main thread

DispatchQueue.main.async {
    self?.view.addSubview(someView)
}

Also, since you're adding the views in a loop, you might look into this answer. It has a really great explanation about the UI updates getting bottlenecked.

One more thing I noticed is,

for var i in (0..<items!.count)

If items is nil, your code will crash. You can do it with conditional binding to make sure it doesn't crash.

if let items = items{
    for item in items{
        //Do your stuff
    }
}
Community
  • 1
  • 1
ebby94
  • 3,131
  • 2
  • 23
  • 31
  • thanks man, it solved my problem and thanks for the advice on the UI bottleneck I´m going to check it – lestat May 11 '17 at 02:25