Search code examples
iosswiftuiimageviewcgimagemultipeer-connectivity

UIImageView Update not drawing until after touch events


My tldr question is:

Why is my UIImageView only updating its image when being drawn on from local touches rather than revieving points to draw from a Multipeer-connectivity session?

Currently my application works as follows:

A user draws on the screen, if the user is connected to a peer using MultipeerConnectivity the peer should see whatever the other user drew appear on their own screen. The drawLine function uses CGContextStrokePath() to draw a line:

drawLine(fromPoint: CGPoint,toPont: CGPoint){
    UIGraphicsBeginImageContext(self.view.frame.size);

    //... do the drawing of the line

    let image = UIGraphicsGetImageFromCurrentImageContext();
    canvas.image = image;
    UIGraphicsEndImageContext()
}

the drawLine method is called from two different sources, either in the override methods touchesMoved(), or touchesEnded() or in the following method which handles receiving data (two CGPoints to draw a line between) from a Multipeer-connectivity session:

func handleMPCReceivedDataWithNotification(notification : NSNotification){
    let receivedDataDictionary = notification.object as! Dictionary<String, AnyObject>
    let data = receivedDataDictionary["data"] as? NSData

    let dataDictionary = NSKeyedUnarchiver.unarchiveObjectWithData(data!) as! Dictionary<String, AnyObject>

    if let pointData = dataDictionary["points"] as! Dictionary<String,AnyObject>!{
        let fromPointObj = pointData["fromPoint"] as! NSValue!
        let toPointObj = pointData["toPoint"] as! NSValue
        let toPoint = toPointObj.CGPointValue()
        let fromPoint = fromPointObj.CGPointValue()

        drawLineFrom(fromPoint, toPoint: toPoint)
    }
}

My issue is that when I draw a line on one device it draws fine locally, and the drawLine method is being called on the other device (as I can see from breaks and prints), but the other device won't actually update the canvas image until the device is drawn on by its own user(i.e. a touch event occurs). So is it that my canvas UIImageView just isn't updating itself until a TouchEvent is called on it? I've tried to find a way for it to be forced to update (for example when I call canvas.image = image I thought it would automatically update), but I have not been able to solve this.

Anyways, any suggestions or input is greatly appreciated

William


Solution

  • At first glance, I think the problem is that your graphics code must be executed on the main thread. The drawing caused by touch events are definitely on the main thread, but it looks like the function handleMPC... is called on a background thread. Put the drawLineFrom invocation inside this:

    dispatch_async( dispatch_get_main_thread(), { drawLineFrom( fromPoint, toPoint: toPoint ) })