DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Deploy Your Angular App on GitHub Pages
  • Applying CI/CD to Java Apps Using Spring Boot
  • Deploy MuleSoft App to CloudHub2 Using GitHub Actions CI/CD Pipeline
  • Unlock the Power of Software Heritage Archive

Trending

  • A Guide to Data-Driven Design and Architecture
  • Podman Desktop Review
  • Agile Estimation: Techniques and Tips for Success
  • GenAI-Infused ChatGPT: A Guide To Effective Prompt Engineering
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. The Plum-O-Meter: Weighing Plums Using 3D Touch in Swift

The Plum-O-Meter: Weighing Plums Using 3D Touch in Swift

My latest app, the Plum-O-Meter, has been specifically designed to weigh plums. I originally built this app for grapes, but they're too light to activate the 3D Touch.

Simon Gladman user avatar by
Simon Gladman
·
Oct. 26, 15 · Tutorial
Like (2)
Save
Tweet
Share
4.69K Views

Join the DZone community and get the full member experience.

Join For Free

Here at FlexMonkey Towers, the ever beautiful Mrs. FlexMonkey and I love to spend our Sunday mornings luxuriating in bed drinking Mimosas, listening to The Archers omnibus and eating some lovely plums. Being a generous sort of chap, whenever I pull a pair of plums from the freshly delivered Fortnum & Mason's hamper, I always try to ensure she has the larger of the two. However, this isn't always easy, especially after the third of fourth breakfast cocktail.

3D Touch to the rescue! My latest app, the Plum-O-Meter, has been specifically designed to solve this problem. Simply place two delicious plums on the iPhone's screen and the heavier of the two is highlighted in yellow so you can hand it to your beloved without fear of being thought of as a greedy-guts.

Lay Your Plums on Me

Plum-O-Meter is pretty simple stuff: when its view controller's touchesBegan is called, it  adds a new CircleWithLabel to its view's layer for each touch. CircleWithLabel is a CAShapeLayer which draws a circle and has an additional CATextLayer. This new layer is added to a dictionary with the touch as the key. The force of the touch is used to control the new layer's radius and is displayed in the label:

    var circles = [UITouch: CircleWithLabel]()

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
    {
        label.hidden = true

        for touch in touches
        {
            let circle = CircleWithLabel()

            circle.drawAtPoint(touch.locationInView(view),
                force: touch.force / touch.maximumPossibleForce)

            circles[touch] = circle
            view.layer.addSublayer(circle)
        }

        highlightHeaviest()

    }


When the touches move, that dictionary is used to update the relevant CircleWithLabel for the touch and update its radius and label:

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
    {
        for touch in touches where circles[touch] != nil
        {
            let circle = circles[touch]!

            circle.drawAtPoint(touch.locationInView(view),
                force: touch.force / touch.maximumPossibleForce)
        }

        highlightHeaviest()

    }


Both of these methods call highlightHeaviest(). This method loops over every touch/layer item in the circles dictionary and sets the isMax property on each based on a version of the dictionary sorted by touch force:

    func highlightHeaviest()
    {
        func getMaxTouch() -> UITouch?
        {
            return circles.sort({
                (a: (UITouch, CircleWithLabel), b: (UITouch, CircleWithLabel)) -> Bool in

                return a.0.force > b.0.force
            }).first?.0
        }

        circles.forEach
        {
            $0.1.isMax = $0.0 == getMaxTouch()
        }

    }

isMax sets the layer's fill colour to yellow if true.


When a plum is removed from the screen, its CircleWithLabel layer is removed and the relevant entry removed from the circles dictionary. Because the heaviest needs to be recqlucated, highlightHeaviest is also invoked:

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
    {
        for touch in touches where circles[touch] != nil
        {
            let circle = circles[touch]!

            circles.removeValueForKey(touch)
            circle.removeFromSuperlayer()
        }

        highlightHeaviest()

    }


In Conclusion

The value displayed is actually the normalized force as a percentage. It's interesting to see that it changes depending on other forces acting upon the screen which to me indicates that the 6s isn't going to replace your high precision electronic scales. What this demo does show is that the 6s can handle multiple touch points each with a decent value for their relative forces.


I did originally build this app for grapes, but they're too light to activate the 3D Touch.


Of course, for such an important piece of software, I've made the source code available at my GitHub repository here. Enjoy! 

Swift (programming language) Dictionary (software) app Label GitHub Precision (computer science) IT Sort (Unix) Repository (version control)

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Deploy Your Angular App on GitHub Pages
  • Applying CI/CD to Java Apps Using Spring Boot
  • Deploy MuleSoft App to CloudHub2 Using GitHub Actions CI/CD Pipeline
  • Unlock the Power of Software Heritage Archive

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: