Where to put my Struct to keep classes independent? - swift

I have a class which I want to be reusable (for any developer user who wants it, or outside my project). This class returns a Struct lets call it structA, and the class is classA.
The first thought is to put structA inside the same file of this class, so while the Struct is public, any user who get this class file can read this Struct which the class returns.
Till here it looks reasonable. (or not)
But what happens if other classes in my current project also need to use this Struct for other purposes? (a copy of it)
Then to make the code reusable I need to put this struct somewhere else.
By reusable I mean there are no dependencies- get the class file and that is it.
If it's outside classA, then classA becomes not reusable and dependent.
If it's inside classA, then other class that use it are also dependent(not reusable outside)
The only solution left is to create other Structs like this with different names(sounds bad)
Where would you put this Struct in your Xcode project?

Put your struct in a separate file and document for each class you want to reuse that it depends on this struct. So basically you make your struct reusable as well.
The process of reusing your class becomes a little bit harder - you also have to include it’s dependencies. But that is just a fact of life, basically all software has dependencies. To make it easier to add some code dependency manages such as Cocoapods, Carthage or the Swift Package Manager have been invented. With those you specify for each library what it depends on - so ClassA depends on StructA. In the project you want to use ClassA you specify only that dependency and the package manager installs all of it’s dependencies (and their dependencies and so on) together.

You can create a separate library or framework which will contain all the reusable classes and structs.
Whenever you want to use the class classA or the struct structA, you can just import that library in the respective file.
Repeating the code is not recommended.

Related

Access class in different file

I'm still a newbie to swift and I can't get a clear answer on a couple things.
So far I've just been using a single file in playgrounds.
If I want to use more files, how can I access data (variables and functions) from classes created there in my main file that controls the view?
From what I understand having multiple files would just be for convenience so I don't have could to write it again.
(Also on the side) what does it mean when a function has private, public or just 'func'?
I'm using swift 3 playgrounds
Thanks
Making things public will make them importable from other modules. Making it private will make it only accessible by methods within its containing scope (encapsulation). For code that lives at the top level, this scope is the entire .swift file it lives in. Without either access modifier (just bare “func”), your thing will default to internal, which means it is accessible from any other code within the same module, but not by code in a different module.
A special case is the fileprivate modifier which restricts access to the .swift file the code lives in. For code that does not live in a class or struct, this does the exact same thing as private. Some Swift designers discourage use of this modifier, and it may be removed in future versions of Swift.
There is a fifth access modifier in Swift, open, which does the exact same thing as public, except it also allows subclassing, and only applies to classes. This one is rarely used, but useful for certain library interfaces.
To import all the public symbols in a module, use
import Module
To import a single public symbol, use
import var Module.variable
import func Module.function
import struct Module.structure
import class Module.class
...

Swift: access level between `private` and `internal`?

In my Swift code, I often use the private modifier to limit the visibility of helper classes. For example, in one file, I'll have a GridController and a GridControllerModel.
The GridController (the UI) should be accessible to the rest of the application, but the model class is wholly internal and should never be accessed by the rest of the application.
I can address this in Swift by making both classes private and keeping them in the same file. But this gets unwieldy as classes get bigger. What I'd like to do is keep each class in a separate file (for programming convenience), but prevent access to the model class anything but GridController (for information hiding purposes).
Is there any way to do this in Swift?
As others have said, there is no way to do exactly what you want today in Swift.
One alternative is to use an extension in another file to add GridControllerModel as a nested subtype of GridController. e.g.
//GridControllerModel.swift
extension GridController {
struct GridControllerModel {
let propertyOne:String
let propertyTwo:String
}
}
This allows your GridController class in its own separate file to declare something like:
var model = GridControllerModel()
However, the rest of the application can still access the GridControllerModel type like this:
//SomeOtherClass.swift
var nested = GridController.GridControllerModel()
So, you do achieve some separation by making the model type a subtype of GridController, but it isn't true access control. On the plus side, it will not appear in code completion outside of the GridController class as "GridControllerModel", you would need to first type "GridController" and then "." to see the subtype "GridController.GridControllerModel"
It's also worth noting that an additional access control level is currently under review and likely to be in the next version of Swift (3.0) :
https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md
Assuming this proposal is accepted and implemented, you would be able to update your declared subtype like this:
//GridControllerModel.swift
local extension GridController {
struct GridControllerModel {
let propertyOne:String
let propertyTwo:String
}
}
(Note the "local" keyword above now). This would make the GridControllerModel type invisible and inaccessible to all classes except GridController and any extensions of GridController.
So, I would recommend that you consider this nested subtype approach today, because when Swift 3.0 arrives later this year, it's likely to support what you want by simply adding a keyword in front of your subtype declaration. And in the meantime, you get some of the separation you want as well.
No, there isn't an access modifier that restricts visibility to only a certain set of files. But you probably don't need that.
What does exist:
private: restricts visibility to within the same source file.
internal: restricts visibility to within the same module.
If you're building a piece of software that's too big for one source file, but both defines an outward-facing interface and internal details that should stay hidden from clients of that interface... then you're probably working at a level where it's appropriate to build a framework. Your framework can then define features that are internal for its use only and separate from the public interface it exposes to clients.

Submodules in Swift

Say I have an app, MyApp which is built in an Xcode workspace. Inside this workspace I have the primary app target and two nested Xcode projects for my frameworks, Foo and Bar.
Inside my app I import Foo and Bar and dependency inject an object in Foo into an object in Bar. Say, however, I don't need all of Foo, just a couple of classes. How could I create a submodule within foo and import that. E.g. import Foo.Models.Animals.Dog
While you can do something like
import struct MyModule.MyStruct
import func Darwin.glob
I'm not sure if you can get much deeper than that. Here's a relevant quote from the (free) Swift book
“Providing more detail limits which symbols are imported—you can specify a specific submodule or a specific declaration within a module or submodule. When this detailed form is used, only the imported symbol (and not the module that declares it) is made available in the current scope.”
It goes on to explain that you can import any of typealias, struct, class, enum, protocol, var, or func
It looks as though Swift has some type of support for submodules (they're mentioned offhand a few places), but I'm not sure we have the ability to actually compile those just yet.

Intersystems caché - programmatically create new class

Is it possible to write ObjectScript method, which will create new class in namespace and compile it? I mean programmatically create new class and store it. If so, can I edit this class using ObjectScript later(and recompile)?
Reason: I have class structure defined in string variable and I need to add new class to namespace according this string.
Nothing is impossible. Everything in Caché can be created programmatically. And, Classes is not a execution. There are at least two ways to do it:
simple SQL Query CREATE TABLE, will create a class.
and as you already mentioned ObjectScript Code, which can do this.
All of definition of any classes defined in other classes. Which you can find in package %Dictionary.
The class itself defined in %Dictionary.ClassDefinition. Which have some properties, for defining any parts of classes. So, this is a simple code which create some class, with one property.
set clsDef=##class(%Dictionary.ClassDefinition).%New()
set clsDef.Name="package.classname"
set clsDef.Super="%Persistent"
set propDef=##class(%Dictionary.PropertyDefinition).%New()
set propDef.Name="SomeProperty"
set propDef.Type="%String"
do clsDef.Properties.Insert(propDef)
do clsDef.%Save()
And in latest versions, there is one more way for create/change class. If you have text of class as you can see it in Studio. Then, you can load it in Caché, with class %Compiler.UDL.TextServices
Yes, it is. You likely want to make use of %Dictionary.ClassDefinition and the related %Dictionary.*Definition classes (especially %Dictionary.PropertyDefinition, %Dictionary.MethodDefinition and %Dictionary.IndexDefinition) to create and/or modify your class. Provided your string contains some reasonable representation of the data, you should be able to create the class this way.
The actual class documentation is available at http://docs.intersystems.com/cache20141/csp/documatic/%25CSP.Documatic.cls?CLASSNAME=%25Dictionary.ClassDefinition
You can then compile the class by calling $system.OBJ.Compile("YourPackage.YourClass","ck").
(Note: If your string contains the exported XML definition of the class, you could also write the XML representation to a stream and then call $system.OBJ.LoadStream() to import the XML definition. I would only recommend this if you have an exported class definition to start with.)

Is it acceptable to create multiple classes in one .swift file, or should I create a separate .swift file for each class?

Is it considered poor technique to create multiple classes in one swift file, or is it best to create a separate swift file for each class?
For example, which is better:
A. Multiple classes in ViewController.swift:
1. alpha.swift:
class alpha: UIViewController { ... }
class beta: UIWebView { ... }
class gamma: UINavigationController { ... }
B. Separate .swift files for each class:
1. In alpha.swift:
class alpha: UIViewController { ... }
2. In beta.swift:
class beta: UIWebView { ... }
3. In gamma.swift:
class gamma: UINavigationController { ... }
Short answer: it depends.
Long answer:
If you have small short classes that are strongly binded together, it's correct to put the in the same file.
If you have long, unrelated classes, then you better put them in different files.
It's not a poor technique, IF the classes are connected.
To decide if they are connected, ask: Can one class be used without the other?
If yes, then you should have two different files, since you might need to use just one of the two.
For example, in C++, collections have an inner class for their iterators. (I know it's a C++ example, but the question isn't really language related).
Though if the classes have nothing to do with each other (being on the same view doesn't count), then they should each have their separate classes.
I have different answer for this question based on painful debugging and searching in the internet for last few days. I'm c++ dev with more than 15 years experience. Coming from this language I'm familiar with few design techniques which needs protected access. Since Swift doesn't support it and as it turns out they won't support it in near future, I've start using private access and write few classes in the same file. That way I've workaround the missing protected modifier (private functions are visible in the same file, so they will be visible for all classes in the same file, and if these classes are derived classes the private is actually working as protected). Well everything is fine and I was happy before found out that my application crashed with EXC_BAD_ACCESS code=1 ... The exceptions was not because of my code, it was because it layout of the members were somehow wrong. For example if i called one function a() from the derived class through instance variable the func b() was called. The b() was also member of the same class and was define before the a(). That is why some functions thrown bad access exception. Instance pointer was corrupt. After I moved all 3 classes to independent files everything looked fine.
Not sure that this was the actual reason or I've done something wrong, but not 100% of cases when you define multiple classes in the same file will be with defined behaviour. May be that is compiler problem, Swift is young language and even that I'm testing with Gold Master studio which is supposed to be stable, there are still a lot of bugs.