Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift:到结构,还是不到结构_Ios_Swift_Class_Struct - Fatal编程技术网

Ios Swift:到结构,还是不到结构

Ios Swift:到结构,还是不到结构,ios,swift,class,struct,Ios,Swift,Class,Struct,我终于从Objective-C转到Swift了。我正在为我的客户创建一个视图布局系统,使他们的应用程序在布局上更加灵活,而不使用自动布局,因为他们希望远程设计屏幕,而自动布局对他们来说太复杂了。我尝试使用structs和protocols来实现这一点,但我发现它相当笨拙,因此我怀疑我的想法不正确 对于类,结构如下所示: class ViewModel { var frame: CGRect = .zero } class ViewGroupModel: ViewModel {

我终于从Objective-C转到Swift了。我正在为我的客户创建一个视图布局系统,使他们的应用程序在布局上更加灵活,而不使用自动布局,因为他们希望远程设计屏幕,而自动布局对他们来说太复杂了。我尝试使用
structs
protocols
来实现这一点,但我发现它相当笨拙,因此我怀疑我的想法不正确

对于类,结构如下所示:

class ViewModel {
    var frame: CGRect = .zero
}

class ViewGroupModel: ViewModel {
    var weight: Int = 1
    var children:[ViewModel] = [ViewModel]()
}

class HorizontalViewGroupModel: ViewGroupModel {
}

class VerticalViewGroupModel: ViewGroupModel {
}
我试图通过定义一个
ViewModel
协议和一个
ViewGroupModel
协议来使用协议,但我发现它创建了大量重复(属性)。有更好的方法吗?在这种情况下使用类是否被认为是一种好的做法


编辑:如果不使用类会更好,我正在寻找一个答案,它可以为我提供一个具体的解决方案,包括
结构
协议

通常,只有在需要类的特殊功能时才使用类,这些功能是:

  • 一个类可以有一个超类和/或一个子类;结构不能

  • 类是值类型,而结构是值类型

  • Objective-C可以内省类(特别是如果它派生自NSObject),但它甚至看不到Swift中声明的结构


编写接口/协议代码总是比编写类/结构代码好。这是你的模型。 为此,您也可以使用泛型。我希望它能为您节省很多变量和重复。 在我看来,出于布局目的,结构加上协议和泛型将是一个伟大的设计。我不认为你有必要在你的案例中使用类。 了解一个特性的内部和外部总是好的,这样可以更好地使用它。Swift中结构和类之间的主要区别是

  • 类对象作为引用存储/传递,而as结构实例作为值存储/传递
  • 引用计数允许对类实例进行多个引用
  • 对于类,我们有标识运算符===和!==用于检查两个变量或常量是否引用类的同一实例。对于Struct,不会出现标识运算符的问题,因为两个不同的Struct变量或常量不能指向同一个实例。您可以尝试将标识运算符应用于结构类型。您将得到编译时错误
  • 继承使一个类能够继承另一个类的特征
  • 类型转换使您能够在运行时检查和解释类实例的类型
  • Deinitializers使类的实例能够释放已分配的任何资源

  • 关于详细的讨论,你可以通过我的帖子。

    如果问题仅仅是如何实现协议的属性,我不一定会让它影响我在
    struct
    vs
    class
    之间的选择。如果您的
    struct
    类型必须实现多种属性,则有两个基本选项:

  • 如果您谈论的是一些属性,那么只需在
    结构中实现符合该协议的那些属性即可。我们一直都这样做。例如,在定义符合
    MKAnnotation
    的自定义类型时,我们只需实现三个必需的属性

    当然,如果我们讨论的是一组更大的属性,这会变得很乏味,但是编译器会在整个过程中帮助我们,确保我们不会遗漏任何东西。因此,挑战相当小

  • 虽然我不喜欢这种方法,但这表明您可以将共享属性实现为组件,其中您可以使用
    struct
    包装所有这些属性,然后在扩展中实现协议的默认计算属性:

    enum SubviewArrangement {
        case none
        case horizontal
        case vertical
        case flow
    }
    
    struct ViewComponent {
        var frame = CGRect.zero
        var weight = 1
        var subviews = [ViewModel]()
        var subviewArrangement = SubviewArrangement.none
    }
    
    protocol HasViewComponent {
        var viewComponent: ViewComponent { get set }
    }
    
    protocol ViewModel: HasViewComponent { }
    
    extension ViewModel {
        var frame: CGRect {
            get { return viewComponent.frame }
            set { viewComponent.frame = newValue }
        }
        var weight: Int {
            get { return viewComponent.weight }
            set { viewComponent.weight = newValue }
        }
        var subviews: [ViewModel] {
            get { return viewComponent.subviews }
            set { viewComponent.subviews = newValue }
        }
        var subviewArrangement: SubviewArrangement {
            get { return viewComponent.subviewArrangement }
            set { viewComponent.subviewArrangement = newValue }
        }
    }
    
    其中,您可以创建符合
    ViewModel
    的实例,如下所示:

    struct LabelModel: ViewModel {
        var viewComponent = ViewComponent()
    }
    
    var label = LabelModel()
    label.weight = 2
    print(label.weight)
    
    我必须承认,这不是最优雅的方法。(我甚至不愿意展示它。)但它避免了在符合
    ViewModel
    的类型中单独实现所有这些属性

  • 所以,让我们把财产问题放在一边。真正的问题是您应该使用值类型(
    struct
    )还是引用类型(
    class
    )。我认为这是一个启发性的考虑苹果的价值讨论VS参考语义接近尾声(@ 4:15)的视频。它们涉及到那些您实际上可能仍然想要使用类的情况。例如,他们建议您在“复制或比较实例没有意义”时使用引用类型。他们建议在处理“窗口”实例时可以应用此规则。这一点在这里也适用

    除此之外,在我看来,使用值类型来表示视图层次结构并没有多大好处,视图层次结构是引用类型对象的集合。这只会让事情变得更加混乱。我会坚持使用
    类型,因为它将准确地反映它所表示的视图层次

    别误会我的意思:我们太习惯使用引用类型了,所以我认为挑战我们的先入为主的观念并仔细研究一个值类型是否能更好地解决这种情况总是好的。不过,在这种情况下,我不必担心它,只需坚持使用反映正在建模的对象层次结构的
    层次结构即可


    尽管如此,您在问题中提出的类层次结构也感觉不太正确。您实际上可以实例化一个
    ViewModel
    ,以后无法向其中添加子视图(而所有
    UIView
    对象都有
    subview
    属性),这让人感到奇怪。此外,您的水平和垂直组类型也感觉不正确。例如,它是否应该是具有某些“axis”属性的单一类型,如
    UIStackV