Swift - Type has no member - swift

I have a basic class named APIGroup that exists for the sole purpose of subclassing (it is not [yet] used for anything but certain static properties that are accessed by the subclasses). It looks somewhat like this:
public class APIGroup {
public static let someProperty : String = "I am a property!"
}
And I have a subclass, Track, which defines a type method search as follows:
public class Track : APIGroup {
public static func search(name: String) -> Void {
print("Track search initiated. Name: \(name)")
print("And the property is: \(someProperty)")
}
}
These two classes are defined in separate files in the same module. In another target, I import the module and try to call:
import MyModule
MyModule.Track.search("testing...")
But this throws: Type 'Track' has no member 'search'. What am I doing wrong?

Putting this code in a Playground works fine for me:
import Foundation
public class APIGroup {
public static let someProperty : String = "I am a property!"
}
public class Track : APIGroup {
public static func search(name: String) -> Void {
print("Track search initiated. Name: \(name)")
print("And the property is: \(someProperty)")
}
}
Track.search("testing...")
If they are in the same module you do not need to import or use the module name.

Related

Can i create a an iOS framework conforming to an inside protocol and also define the same protocol in my project?

i'm creating a framework the conforms to a certain protocol
MyTestFramework.framework
public protocol SBFProtocol {
static var sharedInstance: SBFProtocol { get }
func GetVersion() -> String
func GetBuildNumber() -> String
}
public final class FrameworkBase : SBFProtocol {
public static var sharedInstance: SBFProtocol = FrameworkBase()
public func GetVersion() -> String {
return "1.0"
}
public func GetBuildNumber() -> String {
return "0"
}
}
Then i redefine that same protocol in my class and i import the framework.
MyProject
import MyTestFramework
public protocol SBFProtocol {
static var sharedInstance: SBFProtocol { get }
func GetVersion() -> String
func GetBuildNumber() -> String
}
var testInstance: SBFProtocol = MyTestFramework.FrameworkBase.sharedInstance
Is there a way to access that framework obj with my own protocol definition ?
i keep getting the error:
Value of type 'MyTestFramework.SBFProtocol' does not conform to specified type 'MyProject.SBFProtocol'
Is there any way to do this?
the reason is i want to pass that framework instance to yet another framework (call it annonymousFramework) and i want it to know only the SBFProtocol and not the entire MyTestFramework
is that in any way possible?
Eventually i solved it this way:
i've wrapped the protocol inside it's own framework project (Containing only one protocol.swift file with all the definitions in it)
And then i included that protocol.framework inside all the projects/frameworks that are using it.
This way the compiler recognises it as the same protocol and another benefit i get from this is that i can enforce a minimum iOS version, valid build architectures and more project setting within my protocol/framework hybrid.

Autofac - One interface, multiple implementations

Single interface: IDoSomething {...}
Two classes implement that interface:
ClassA : IDoSomething {...}
ClassB : IDoSomething {...}
One class uses any of those classes.
public class DummyClass(IDoSomething doSomething) {...}
code without Autofac:
{
....
IDoSomething myProperty;
if (type == "A")
myProperty = new DummyClass (new ClassA());
else
myProperty = new DummyClass (new ClassB());
myProperty.CallSomeMethod();
....
}
Is it possible to implement something like that using Autofac?
Thanks in advance,
What you are looking for is, as I remember, the Strategy Pattern. You may have N implementations of a single interface. As long you register them all, Autofac or any other DI framework should provide them all.
One of the options would be to create a declaration of the property with private setter or only getter inside Interface then implement that property in each of the class. In the class where you need to select the correct implementation, the constructor should have the parameter IEnumerable<ICommon>.
Autofac or any other DI frameworks should inject all possible implementation. After that, you could spin foreach and search for the desired property.
It may look something like this.
public interface ICommon{
string Identifier{get;}
void commonAction();
}
public class A: ICommon{
public string Identifier { get{return "ClassA";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class A: ICommon{
public string Identifier { get{return "ClassB";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class Action{
private IEnumerable<ICommon> _common;
public Action(IEnumerable<ICommon> common){
_common = common;
}
public void SelectorMethod(){
foreach(var classes in _common){
if(classes.Identifier == "ClassA"){
classes.commonAction();
}
}
}
}

Unable to call initializer for subclass of generic type

UPDATE: Question and title have been restated based on changes that were made in response to the initial question.
I've got a base class that implements a generic class method for creating new instances. The simplified logic of this class method is as follows
class MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MyBaseClass.init")
// Initialize base class from record
}
class func retrieveInstance<T:MyBaseClass>(name:String, callback:(T) -> ()) {
let myRecord:MyRecordType = ... // Perform fetch to get a record for name
let result = (T.self as T.Type)(myRecord) // Code currently crashes with BAD_ACCESS at this line
callback(result)
}
}
I then implement a subclass of this base class with logic like the following
class MySubClass : MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MySubClass.init")
// Initialize subclass from record
super.init(record)
}
}
Next, I try to invoke the generic class method
class AnotherClass {
func successCallback(result:MySubclass) {
// Handle callback
}
MySubClass.retrieveInstance("objectName", callback:successCallback)
}
When creating an instance of the class - the line marked with a comment identifying the crash location - I am expecting the init method from MySubClass to be invoked. (This odd notation is based on the bug workaround suggested in the replies)
Instead of calling the init method for MySubClass, this code crashes with a BAD_ACCESS. I have been unable to find any nil references or anything else that would explain this crash.
With a lot of help from the answer originally posted by #rintaro, I was able to solve this problem, although there is still an oddity that I will post under a separate question.
As it turns out, #rintaro was absolutely correct in the need to initialize the instance of the generic type using the following syntax:
let result = (T.self as T.Type)(myRecord)
This works as long as the base class MyBaseClass declares this initializer with a required tag:
public class MyBaseClass {
public required init(_ record:MyRecordType) {
...
}
}
and the subclass MySubClass implements the matching initializer:
public class MySubClass : MyBaseClass {
public required init (_ record:MyRecordType) {
...
super.init(record)
}
}
Where things fail, however is when I actually have a 3-level class hierarchy and the initializer hierarchy throughs an override into the mix. To envision this, consider a set of class that represents nodes in a tree structure:
public class Node {
public init(_ record:MyRecordType) {
...
}
}
public class RootNode : Node {
override public init(_ record:MyRecordType) {
...
super.init(record)
}
public class func <T:RootNode>retrieveAll(success:(T) -> ()) {
// Retrieve all instances of root node subclass T, and invoke success callback with new T instance
}
}
public class ChildNode : Node {
public init(_ record:MyRecordType, parentNode:Node) {
...
super.init(record)
}
public class func <T:ChildNode>retrieveChildren(parent:Node, success:(T) -> ()) {
// Retrieve all child T instances of parent node, and invoke success callback with new T instance
{
}
The problem occurs in the implementation of the RootNode class's retrieveAll method. In order for it to work as described by #rintaro, I need the init in RootNode to be marked with the required keyword. But because it also overrides the initializer from Node, it also needs to have the override keyword. So I try to use both keywords in the declaration:
override required public init(_ record:MyRecordType) {
...
}
The Swift compiler accepts this, but when I use it to initialize an instance from within the retrieveAll method, it crashes with a BAD_ACCESS.
I was able to work around this problem by changing the method signature of the NodeClass just slightly so that its RootNode subclass doesn't need to override:
public class Node {
public init(record:MyRecordType) {
...
}
}
public class RootNode {
public required init(_ record:MyRecordType) {
...
super.init(record:record)
}
}
By doing this workaround, my subclasses of RootNode can properly implement the required initializer, and the retrieveAll method in RootNode can properly instantiate instances of those subclasses.

swift - how to access public constants without having to instanciate class, as in C#

Should not be needed create an instance of a class to access a public constant. I recently started working in Swift, so I must be missing something here.
In this simple example:
public class MyConstants{
public let constX=1;
}
public class Consumer{
func foo(){
var x = MyConstants.constX;// Compiler error: MyConstants don't have constX
}
}
This foo code gives an compile error. To work, I need to create an instance of the MyConstants like this:
public class Consumer{
func foo(){
var dummy = MyConstants();
var x = dummy.constX;
}
}
Adding static to constX is not allowed.
Use struct with static types.structare more appropriate as in enum you can only bind one type of associative values but you can contain the "Type Property of any type" in both.
public struct MyConstants{
static let constX=1;
}
public class Consumer{
func foo(){
var x = MyConstants.constX;
}
}
You should use immutable static variables. Unfortunately classes support computed properties only with the class modifier - the compiler outputs an error stating that class variables are not yet supported.
But in structs it's possible to create static data members:
struct Constants {
static let myConstant = 5
}
and of course it's not required to create an instance, as the immutable static property can simply be accessed as:
Constants.myConstant
If you want a constant, you can also "fake" the as-yet-unsupported class variable with a class computed property, which does currently work:
public class MyConstants{
public class var constX: Int { return 1 };
}
public class Consumer{
func foo(){
var x = MyConstants.constX; // Now works fine.
}
}
For string constants what I do is put the bunch of constants into responsible class file in the following way:
public enum NotificationMessage: String {
case kTimerNotificationId = "NotificationIdentifier"
}
Then for use it from any other point of the code just:
println("\(NotificationMessage.kTimerNotificationId.rawValue)")
Do not forget .rawValue.
I found out the solution below, but hope someone can clarify or post a better solution
enum MyConstantsV2 {
static var constX = 1
}
public class Consumerv2{
func foo(){
var x = MyConstantsV2.constX;
}
}

Static/Global variables problems

//main.fla
var skill1 = addChild(girl2.skill1);
i want to access the skill1 var in girl2.as, but it didn't work.
The error was shown :
1119: Access of possibly undefined property skill1 through a reference with static type Icons.chars:girl2.
//girl2.as
package Icons.chars
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.net.URLRequest;
public class girl2 extends charsel {
public static var skill1:Loader, url1:URLRequest;
public function girl2 () {
skill1 = new Loader();
url1 = new URLRequest("skills/nami/skill4.png")
skill1.load(url1);
I tried in charsel.as and it worked
//charsel.as
package Icons.chars
{
import flash.geom.Point;
import flash.display.*;
import flash.events.MouseEvent;
public class charsel extends MovieClip {
protected var originalPosition:Point;
public static var player1:MovieClip, player2:MovieClip, player3:MovieClip;
I tried to access player1 and it worked.
I am not sure why you would want to use a static modifier in this case. Note, that even though you have declared skill1 as a static it will actually become available only when you create an instance of the girl2 class - as you creating it in the constructor (also note, that you should name your classes with a capital letter, so this should be Girl2).
So, I would either remove all static modifiers for public variables or, if there are any specific reasons for that, use a static initialiser to instantiate skill1 variable:
public class girl2 extends charsel {
public static var skill1:Loader, url1:URLRequest;
{
skill1 = new Loader();
skill1.addEventListener(...); // event handlers should be static as well
skill1.load(...);
}
public function girl2 () {