Biến lớp chưa được hỗ trợ


93

Tôi bắt đầu dự án của mình với bộ điều khiển chế độ xem phân tách làm bộ điều khiển chế độ xem ban đầu và bắt đầu nó tự động từ bảng phân cảnh.

Nói chung, một ứng dụng có giao diện người dùng này có một và chỉ một bộ điều khiển chế độ xem phân tách làm gốc, vì vậy tôi tạo một biến tĩnh trong lớp con và đặt nó khi quá trình khởi tạo hoàn tất.

Vì vậy, tôi muốn thử hành vi này một cách nhanh chóng.

Tôi đã đọc cuốn sách hướng dẫn ngôn ngữ lập trình Swift trên iBook về thuộc tính Type (với từ khóa static và class) và thử một đoạn mã cho công việc:

import UIKit

class SplitViewController: UISplitViewController {

    class func sharedInstance() -> SplitViewController {
        return SplitViewController.instance
    }

    class let instance: SplitViewController = nil

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.initialization()
    }

    init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder);
        self.initialization()
    }

    func initialization() {
        SplitViewController.instance = self;
    }
}

nhưng tôi đã tìm ra khi Xcode nói rằng từ khóa lớp cho thuộc tính kiểu chưa được hỗ trợ.

chi tiết lỗi trong hình ảnh

Bạn đã có một giải pháp để làm điều này?


Điều gì xảy ra nếu bạn thay thế 'let' bằng 'var'?
ZunTzu

Nó tạo ra cùng một lỗi.
Cezar

1
Đó là hạt giống đầu tiên, hãy bình tĩnh. :) Nếu cuốn sách nói rằng nó được hỗ trợ và nó chưa có sẵn, nó sẽ là. Ngay cả lỗi nói "chưa" .
akashivskyy

1
Có @akashivskyy bạn đã lý do nhưng có thể nó có thể và không bị lỗi đứng về phía tôi và ai đó có một giải pháp để làm hành vi này ...
Vincent Saluzzo

1
@lespommes Apple nổi tiếng là kín tiếng về bất cứ điều gì đang chờ xử lý. Thật đáng xấu hổ cho họ khi thiếu một tính năng tiêu chuẩn và rõ ràng như vậy trong bản phát hành khổng lồ của ngôn ngữ hàng đầu mới của họ. Cần có nhiều cải tiến trước khi Swift sẵn sàng để sử dụng nghiêm túc.
Cường điệu

Câu trả lời:


37

Swift hiện đã hỗ trợ các biến tĩnh trong các lớp. Điều này không hoàn toàn giống với một biến lớp (vì chúng không được kế thừa bởi các lớp con), nhưng nó giúp bạn khá gần gũi:

class X {
  static let y: Int = 4
  static var x: Int = 4
}

println(X.x)
println(X.y)

X.x = 5

println(X.x)

1
Như Bill nói, điều đó không giống nhưng đó là điều tôi cần!
Vincent Saluzzo

@VincentSaluzzo, (và Bill) Sự khác biệt giữa biến này và biến lớp là gì?
skywinder

Tài liệu của Apple gần đây đã thay đổi để cập nhật trạng thái: developer.apple.com/library/ios/documentation/Swift/Conceptual/… Trên thực tế, classtừ khóa hiện chỉ có thể được sử dụng cho các thuộc tính tính toán và static dành cho tất cả các thuộc tính kiểu (trong enum, class hoặc cấu trúc)
Vincent Saluzzo

@skywinder Như tôi đã đề cập trong câu trả lời của mình, các biến lớp đúng có thể được kế thừa bởi các lớp con. Biến tĩnh không thể.
Hóa đơn

@VincentSaluzzo Apple có cập nhật tài liệu của mình không? developer.apple.com/library/ios/documentation/Swift/Conceptual/… xem đoạn thứ tư: "Đối với các kiểu giá trị (nghĩa là cấu trúc và kiểu liệt kê), bạn có thể xác định các thuộc tính kiểu được lưu trữ và tính toán. Đối với các lớp, bạn có thể chỉ xác định các thuộc tính kiểu được tính toán. "
fujianjin6471

73

Nhúng một cấu trúc có thể hoạt động tốt như một cách giải quyết:

class SomeClass
{
  // class var classVariable: Int = 0
  // "Class variables not yet supported." Weird.

  // Workaround:
  private struct SubStruct { static var staticVariable: Int = 0 }

  class var workaroundClassVariable: Int
  {
    get { return SubStruct.staticVariable }
    set { SubStruct.staticVariable = newValue }
  }
}

Sau đó, thuộc tính kiểu tính toán SomeClass.workaroundClassVariable có thể được sử dụng như thể nó là thuộc tính kiểu được lưu trữ.


1
Làm việc cho tôi - ngoại trừ việc tôi phải bỏ 'công khai' vì XCode 6.0 không thích tôi khai báo một lớp công khai trong một lớp nội bộ.
Ali Beadle

Hoạt động tốt, ngoại trừ việc xcode không cho phép kiểu lồng nhau trong kiểu chung ... vì vậy nếu bạn có một lớp chung, có vẻ như vô vọng vì chỉ có các thuộc tính được tính toán là có thể.
BenMQ

19

Dường như có thể khai báo các biến có thời lượng lưu trữ tĩnh trong phạm vi tệp (như trong C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}

mmmh, tại sao không, nhưng xác định var ở phạm vi tệp không làm rò rỉ bộ nhớ trong thời gian dài sử dụng?
Vincent Saluzzo

@VincentSaluzzo Không có gì khác biệt so với những gì bạn đã làm trước Swift: lưu trữ cá thể duy nhất trong một biến tĩnh. Không có gì bị rò rỉ ở đây, ngoại trừ một phiên bản duy nhất tồn tại miễn là quá trình.
Nikolai Ruhe

Tôi đã thử điều này trong sân chơi với lớp học của riêng tôi. Nó không hoạt động vì lớp chưa được khai báo khi bạn khởi tạo var "tĩnh" đó. Tôi chưa thử nó trong dự án Xcode (tôi đoán nó phải hoạt động ở đó?). Vì vậy, tôi có thể cần phải tìm ra "khai báo chuyển tiếp lớp" như bạn thường làm khi chỉ định giao thức cho một lớp.
kawingkelvin

2
Lưu ý rằng trong Xcode 6.0, bạn không thể có hai biến phạm vi tệp có cùng tên, ngay cả khi chúng giống nhau private.
nschum

@NikolayTsenkov Chính xác.
Nikolai Ruhe

14

Phương pháp ưa thích của tôi là chỉ sử dụng var phạm vi tệp riêng tư bên ngoài lớp và sau đó triển khai getters và setters của lớp / static:

private var _classVar: Int = 0;

class SomeClass
{
    public class var classVar: Int
    {
        get { return _classVar }
        set { _classVar = newValue }
    }
}

5

Kể từ Swift 1.2 (có sẵn với Xcode 6.3b1 trở đi), staticcác thuộc tính và phương thức của lớp được hỗ trợ.

class SomeClass
{
    static var someVariable: Int = 0
}

1
Bạn có hiểu họ chỉ không dùng classbiến hay có sự khác biệt nào (được sử dụng staticcho cấu trúc, classcho lớp) không?
Chris Conover

@chrisco Ghi chú phát hành cho biết đó staticlà bí danh cho class final.
Andreas Ley


4

Một giải pháp đủ tương tự như var trong phạm vi tệp nhưng tùy biến hơn và gần singleton là sử dụng một cấu trúc hỗ trợ var tĩnh làm thuộc tính của lớp

struct PersonSharedData {
    static var backstore = ""
    var data: String {
    get { return PersonSharedData.backstore }
    set { PersonSharedData.backstore = newValue }
    }
}

class Person {
    var shared=PersonSharedData() //<< pseudo class var
    var family: String {
        get { return shared.data }
        set { shared.data=newValue }
    }
    var firstname = ""
    var lastname = ""
    var sexe: Sexe = .Unknown
}

2

Ok, với giải pháp của Nikolai mà làm việc. Tôi đăng những thay đổi của mình trong chủ đề này để biết thông tin

var instance: SplitViewController? = nil

class SplitViewController: UISplitViewController {

    class func sharedInstance() -> SplitViewController? {
        return instance;
    }

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.initialization()
    }

    init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder);
        self.initialization()
    }

    func initialization() {
        instance = self
    }
}

và ví dụ: trong appDelegate của tôi, tôi có thể truy cập vào phương thức tĩnh như thế này

SplitViewController.sharedInstance()!.presentsWithGesture = false

Tôi chỉ tò mò, nhưng biến "instance" có phải là biến toàn cục không? Điều này có nghĩa là nếu bạn có một lớp singleton khác thì biến "instance" của bạn sẽ bị ghi đè, phải không?
Raphael

1

Từ ngữ trong lỗi ám chỉ đây sẽ là một tính năng ngôn ngữ trong tương lai.

Bạn có thể tạm thời muốn khai báo một biến thuộc tính trong Application Delegate và truy xuất nó từ đó. Không phải là lý tưởng, chắc chắn là một mô hình chống, nhưng sẽ cung cấp cho bạn một nơi trung tâm để lấy ra UISplitViewControllerkhi cần thiết.


Không vì trong trường hợp của tôi, SplitViewController là initizalize bởi thời gian chạy khi thức dậy từ kịch bản, vì vậy tôi không thể truy cập trực tiếp đến bộ điều khiển quan điểm này từ đại biểu ứng dụng của tôi
Vincent Saluzzo

1

Bạn phải bọc các biến lớp bên trong một biến cấu trúc bên trong

class Store{
    var name:String
    var address:String
    var lat:Int
    var long:Int
    init(name:String, address:String, lat:Int, long:Int){
        self.name = name
        self.address = address
        self.lat = lat
        self.long=long
    }

    private struct FACTORY_INITIALIZED_FLAG { static var initialized: Bool = false
       static var  myStoreList:[Store]?
        static func getMyStoreList()->[Store]{
            if !initialized{
                println("INITIALIZING")
                myStoreList = [
                    Store(name: "Walmart", address: "abcd", lat: 10, long: 20),
                    Store(name: "JCPenny", address: "kjfnv", lat: 23, long: 34)
                ]
                initialized = true
            }
                return myStoreList!
    }
    }
}


var a = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()

var b = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()

// only prints INITIALIZING once

0

Thử cái này:

class var instance: SplitViewController {
    return nil
}

0

Nó được gọi là Thuộc tính kiểu trong Swift.

Bạn xác định thuộc tính kiểu với từ khóa static. Đối với các thuộc tính kiểu được tính toán cho các kiểu lớp, bạn có thể sử dụng từ khóa lớp thay thế để cho phép các lớp con ghi đè việc triển khai của lớp cha. Ví dụ dưới đây cho thấy cú pháp cho các thuộc tính kiểu được lưu trữ và tính toán:

struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Đọc thêm tại liên kết bên dưới,

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID254

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.