UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Error: Instance member cannot be used on type

Forums > 100 Days of SwiftUI

I'm trying to add dates to the Bookworm project, so users can track when they started and finished a book.

I added three new attributes to the core data model: startDate (Date), endDate (Date), and datesRead (String). Then I created three new @State properties for each in AddBookView.swift.

Everything is working fine, except for my computed property.

@State private var startDate = Date()
@State private var endDate = Date()
@State private var datesRead = formatDates

static var formatDates: String {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        let date1 = formatter.string(from: startDate)
        let date2 = formatter.string(from: endDate)
        return "\(date1)-\(date2)"
    }

Two errors occur inside the computed property, where date1 and date2 are declared:

Instance member 'startDate' cannot be used on type 'AddBookView' Instance member 'endDate' cannot be used on type 'AddBookView'

What does this mean?

2      

I think it is because you made your computed property a static property. Your @State private var properties are instance properties, which means that they only exist after you have created an instance of AddBookView somewhere in your program. Those properties would be unique to a single instance of AddBookView.

But when you create a static property, it would exist as long as you have defined the AddBookView structure, even if you never create an instance of AddBookView. That property would not be unique to each instance of AddBookView that you create, but would basically be a property holding a single value that is shared by the AddBookView struct as a whole. So all of the separate instances of AddBookView could have access to it, and get the same value from it, but it wouldn't be a unique value for each instance that looks at it.

So, you are basically telling Swift to create a variable that exists before an instance of AddBookView is created, and initialize it with values that don't exist until after an instance of AddBookView is created. That is why you are not allowed to use them.

3      

I'm thinking that you might be able to just remove the static keyword from your computed property, then remove this whole line

@State private var datesRead = formatDates

and just rename your computed property datesRead instead of formatDates

So you would end up with this...

@State private var startDate = Date()
@State private var endDate = Date()

var datesRead: String {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        let date1 = formatter.string(from: startDate)
        let date2 = formatter.string(from: endDate)
        return "\(date1)-\(date2)"
}

I don't think you need datesRead to be an @State property, because you don't need your view to be updated every time it changes. You are already using @State on your other two dates, so your view would be updated any time one of those is changed, and the computed property would automatically have its new value at that point as well.

Also, I don't think that you need datesRead to be a property in your data model at that point, because it can just be computed from other data that you already have in there. But, I think it is in the next project that you will learn how to add manually written extensions to your data model Entities, which will allow you to create computed properties like this in your Entity's definition, rather than creating it in a separate View's definition like we are doing here.

3      

So that you aren't creating a DateFormatter every time the datesRead variable is computed, you can do...

let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    return formatter
}()

var datesRead: String = {
    let date1 = dateFormatter.string(from: startDate)
    let date2 = dateFormatter .string(from: endDate)
    return "\(date1)-\(date2)"
}

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.