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

SOLVED: How to initialize variables that depend on other variables in views?

Forums > SwiftUI

Hi folks,

I'm trying to create something like the following:

struct someView: View {
   @FetchRequest(sortDescriptors: [SortDescriptor(\.date)]) var books: FetchedResults<Book>
   let bookCategories = BookCategories.booksByDate(books: books)

   var body: some View {
       // ...
     }
}

The problem is that bookCategories line returns the following error.

Cannot use instance member 'todos' within property initializer; property initializers run before 'self' is available

It works successfully if I place let bookCategories = inside the body, but somehow that seems...inelegant(?) Is that the done way?

Similarly, I can get it working by creating an initializer, but I have to:

  • Initialize the fetchrequest inside the init too
  • Assign a default value to bookCategories
  • Therefore, change bookCategories from let to var

All of which seems clumsy.

So I guess the short version of this question is: how do you elegantly initialize variables that rely on other variables?

2      

You can't use variables of property wrappers inside init of a View. Explanation is here.

What you can do is: Fill the variables with the .onAppear modifier.

2      

Hi @Hatsushira - thanks for the response. I like the idea, but moving the let bookCategories... to a .onAppear on the list gives a "cannot find bookCategories in scope" error when referencing it?

2      

@Bnerd  

Hello @baggage, Hatsuhira didn't say to place the "let bookCategories" in the .onAppear, what he meant is

change your let into a var (keep it in the main struct not in the body)

var bookCategories: BookCategories

and in the .onAppear add

bookCategories = BookCategories.booksByDate(books: books)
// or
bookCategories = .booksBydate(books: books)

That's the best I can guess with the code you presented :)

2      

hi @baggage,

i don't know exactly the context of your view or your app, but the bookCategories property depends on the books array ... and because this books array, being defined by a FetchRequest, may change over time (when changes to any of its elements are made elsewhere in your view, or even elsewhere in you app while the view is on screen), you probably don't want to use a let to define bookCategories.

also, you won't be able to set a variable defined by let or var in an .onAppear ... you can only manipulate @State variables after the view is initialized.

a better choice would be to use a computed variable:

var bookCategories: TheTypeReturnedByThisExpression { 
  BookCategories.booksByDate(books: books) 
}

where TheTypeReturnedByThisExpression is whatever type is returned by the booksByDate function defined on BookCategories. i am guessing this is some sort of array type.

hope that helps,

DMG

2      

@delawaremathguy Ach - can't believe I didn't think of that! You're right of course. Many thanks, much appreciated!

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

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.