schaphil
schaphil

Reputation: 13

Simple UIImage animation lags

I am writing a simple app where the clouds move towards an airplane. The plane can be moved with the help of the slider. Since the time can be displayed via a label, the position of the plane always jumps back to default and it lags. Does anyone kindly have a tip for me? I can not find the error :(

Regards Philipp

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var slider: UISlider!
    
    @IBOutlet weak var Label2: UILabel!
    
    @IBOutlet weak var airplane: UIImageView!
    @IBOutlet weak var cloud1: UIImageView!
    
    let screenWidth = UIScreen.main.bounds.size.width
    
    override func viewDidLoad() {
        super.viewDidLoad()
        loop()
    }
    
    
    @IBAction func moveSlider(_ sender: UISlider) {
        let currentValue :Float = sender.value
        
        airplane.center.x = CGFloat(currentValue) * screenWidth

    }
        
    func loop() {
               
        let startDate = Date()
        
        Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { (aTimer) in
                       
            RunLoop.current.add(aTimer, forMode: .common)
            aTimer.tolerance = 0.1

            DispatchQueue.main.async {
                self.cloud1.frame.origin.y += 1.0
                self.Label2.text = String(format: "%.1f", aTimer.fireDate.timeIntervalSince(startDate))
            }
        }
    }
}

Demo: https://i.sstatic.net/7Y10G.jpg

Here my storyboard and constraints:

storyboard

Upvotes: 0

Views: 39

Answers (1)

DonMag
DonMag

Reputation: 77691

The problem is that you have set a CenterX constraint for your Airplane image view, but then you are trying to move it by changing its frame.origin.x. So, every time the screen updates, auto-layout moves that image view back to its CenterX constraint position.

You will want to add an @IBOutlet for that CenterX constraint, and then update its .constant value to move it.

Here's how it should look (just the slider and airplane image view):

enter image description here

If you look where Airplane CenterX is listed in the constraints, that's the imageView constrained horizontally to the slider (centerX to centerX).

This is how the view controller class looks:

class MovePlaneViewController: UIViewController {

    @IBOutlet var slider: UISlider!
    @IBOutlet var airplane: UIImageView!
    
    @IBOutlet var airplaneCenterX: NSLayoutConstraint!

    var sliderInnerWidth: CGFloat = 0

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // because the slider Thumb goes edge-to-edge
        //  we only want to use the ThumbCenter-to-ThumbCenter range
        //  for later positioning
        let trackRect = slider.trackRect(forBounds: slider.bounds)
        let thumbRect = slider.thumbRect(forBounds: slider.bounds, trackRect: trackRect, value: 0)
        sliderInnerWidth = slider.frame.width - thumbRect.size.width
        
        // call your loop func here
        //loop()
    }

    @IBAction func moveSlider(_ sender: UISlider) {
        let currentValue: CGFloat = CGFloat(sender.value)
        
        var xOffset: CGFloat = sliderInnerWidth * currentValue
        // this will make the offset
        //  less-than Zero if slider is less-than 50%
        //  greater-than Zero if slider is greater-than 50%
        xOffset -= sliderInnerWidth / 2.0
        
        // update the airplane's centerX constant
        airplaneCenterX.constant = xOffset
        
    }

}

Here's the Storyboard source, so you can try it out easily (and then implement it with the rest of your code and UI elements):

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="q2w-Zv-3Jg">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Move Plane View Controller-->
        <scene sceneID="jAY-b9-7YF">
            <objects>
                <viewController id="q2w-Zv-3Jg" customClass="MovePlaneViewController" customModule="PanZoom" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="2bg-MF-Dfi">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="12v-ia-vOX">
                                <rect key="frame" x="14" y="607" width="347" height="31"/>
                                <connections>
                                    <action selector="moveSlider:" destination="q2w-Zv-3Jg" eventType="valueChanged" id="pHV-BI-Zst"/>
                                </connections>
                            </slider>
                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrow.up" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="11P-52-E7Q">
                                <rect key="frame" x="67.5" y="473" width="240" height="111"/>
                                <color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="240" id="LYK-Lp-n78"/>
                                    <constraint firstAttribute="height" constant="113" id="sGv-Ri-i7J"/>
                                </constraints>
                            </imageView>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="Yqd-3m-a1U"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="Yqd-3m-a1U" firstAttribute="bottom" secondItem="12v-ia-vOX" secondAttribute="bottom" constant="30" id="0Hj-gj-Hfm"/>
                            <constraint firstItem="12v-ia-vOX" firstAttribute="leading" secondItem="Yqd-3m-a1U" secondAttribute="leading" constant="16" id="1YJ-9h-PtM"/>
                            <constraint firstItem="12v-ia-vOX" firstAttribute="top" secondItem="11P-52-E7Q" secondAttribute="bottom" constant="22" id="9nV-Wx-JhH"/>
                            <constraint firstItem="Yqd-3m-a1U" firstAttribute="trailing" secondItem="12v-ia-vOX" secondAttribute="trailing" constant="16" id="aR0-q8-Slq"/>
                            <constraint firstItem="11P-52-E7Q" firstAttribute="centerX" secondItem="12v-ia-vOX" secondAttribute="centerX" id="q20-KD-Bjr"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="airplane" destination="11P-52-E7Q" id="bNF-1y-ciX"/>
                        <outlet property="airplaneCenterX" destination="q20-KD-Bjr" id="Gd3-s2-Y9e"/>
                        <outlet property="slider" destination="12v-ia-vOX" id="NYl-Lw-OPy"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="Z13-sS-hmx" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="120.8" y="2189.9550224887557"/>
        </scene>
    </scenes>
    <resources>
        <image name="arrow.up" catalog="system" width="120" height="128"/>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

Upvotes: 1

Related Questions