-3

I have hundreds of instance variables in a class. Everytime I work on the class I have to scroll past them.

I would very much like to put them in a different file - like a header file.

I tried using an extension:

extension MyClass {
    var foo = 0
}

But I get the error Extensions must not contain stored properties.

Is it possible to define instance variables outside the main swift class file? I have made extensive use of extensions, but the init methods still need to be in the root class file.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
  • 7
    Why do you have 100s of instance properties on a single class? That most probably signals something is seriously flawed with your code design. And no, you cannot add stored properties to a type in an extension. – Dávid Pásztor Jun 18 '19 at 20:59
  • 1
    I agree, you probably need one or more structs or an array or some combination of those to hold your data, but a simplistic fix is that Swift doesn't care where in the file you declare properties; move the declarations to the bottom of the file. – Paulw11 Jun 18 '19 at 21:11
  • Swift do not support partial class/struct implementation. You can add properties via extensions using `objc_(get|set)AssociatedObject` https://stackoverflow.com/a/34336682/1135154 . But if you have 'hundreds of instance variables' you should split your model. – Kirow Jun 18 '19 at 21:14
  • 1
    @Kirow using Obj-C AssociatedObject to add properties to a class that you have complete control over is a really bad idea. You should never need to use those unless you are working with existing Obj-C classes that you have no control over. – Dávid Pásztor Jun 18 '19 at 21:16
  • There's a very strong chance that every grouping of instance variables you want to put in extensions, should each be a separate new struct/class. – Alexander Jun 18 '19 at 21:16
  • There is a lot to keep track of in the view controller. If I use one or more structs or classes, that doesn't really change much since the struct/class still needs to be populated with the current data. – Jeshua Lacock Jun 18 '19 at 21:40
  • I don't understand all the downvotes. What is wrong with wondering if there is a way to include a header (or similar) with Swift? Also, it's worth mentioning that I don't actually have hundreds of instance variables, I exaggerated a bit to try to make the point of why it might be nice to be able to define them somewhere else. – Jeshua Lacock Jun 19 '19 at 01:54
  • And even if the class had 10 variables, I still think it would be nice to have them in a file of their own. – Jeshua Lacock Jun 19 '19 at 01:56
  • @JeshuaLacock It changes everything. For one, it's a very strong indication that you should break up you view controller so that's more focused. If you have many "sections" of marginally related content, you can split those into separate views with separate VCs. You can also extract things like `UITableViewDataSource/Delegate` to separate classes, and shed weight that way. Big VCs can sometimes be tricky to break apart, but they're almost always going to be a big source of pain, state errors, and other frustrations. – Alexander Jun 19 '19 at 03:08
  • @JeshuaLacock I don't know why you're being downvoted either, but I have a gut feeling that it was just people's gut reaction to seeing "hundreds of instance variables". It's a triggering sentence lol. "And even if the class had 10 variables, I still think it would be nice to have them in a file of their own." I would recommend against this, even if it were possible. You would just be forced to click back and forth between these files, because methods are so heavily coupled to instance variables – Alexander Jun 19 '19 at 03:10
  • I prefer clicking on a file versus scrolling. Going back and forth is very fast with `command-control-arrow`. Plus there is always split view. Besides this case, I still think there are times when being able to import a Swift file into a Swift file would be nice. – Jeshua Lacock Jun 19 '19 at 05:01

2 Answers2

1

This isn't possible.

Objects have a particular memory layout (produced by the compiler) which determines how much memory is needed per object, and where in that memory each of the object's members are stored.

Once an object is created, the layout of its members can't be changed. Even if this was possible, and the runtime had some way of reallocating every object you own of this class, and used the new memory layout, that wouldn't be possible for objects you don't own (in other modules).

Alexander
  • 59,041
  • 12
  • 98
  • 151
0

Disclaimer: I don't condone storing hundreds of instance OR member variables within any class.

Although you cannot define instance variables outside of the main class, you CAN define static variables outside of your main class as follows:

extension MyClass {
    static var foo = 0
}

This is because static variables are member variables of a class which means they belong to the type MyClass NOT an instance MyClass().

In other words, the following

let myobj = MyClass()
print(myobj.foo)

results in the error: Static member 'foo' cannot be used on instance of type 'MyClass'.

BUT MyClass.foo is totally fine because foo is a static member of type MyClass.

I post this because it could be helpful in understanding why you cannot define instance variables outside the main declaration and not misuse static variable declarations.

Sam King
  • 890
  • 1
  • 8
  • 21