ยังไม่รองรับตัวแปรคลาส


93

ฉันเริ่มโปรเจ็กต์โดยใช้ตัวควบคุมมุมมองแยกเป็นตัวควบคุมมุมมองเริ่มต้นและเริ่มโปรเจ็กต์โดยอัตโนมัติจากสตอรี่บอร์ด

โดยทั่วไปแอปที่มี UI นี้จะมีตัวควบคุมมุมมองแยกเพียงตัวเดียวเป็นรูทดังนั้นฉันจึงสร้างตัวแปรแบบคงที่ในคลาสย่อยและตั้งค่าเมื่อเริ่มต้นเสร็จสิ้น

ดังนั้นฉันต้องการลองพฤติกรรมนี้ด้วยความรวดเร็ว

ฉันอ่านหนังสือคู่มือภาษาการเขียนโปรแกรม Swift บน iBook เกี่ยวกับคุณสมบัติ Type (พร้อมคำหลักแบบคงที่และคลาส) และลองใช้โค้ดกับงาน:

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;
    }
}

แต่ฉันพบว่าเมื่อ Xcode พูดว่ายังไม่รองรับคีย์เวิร์ดคลาสสำหรับคุณสมบัติประเภท

รายละเอียดข้อผิดพลาดในภาพ

คุณมีวิธีแก้ไขหรือไม่?


จะเกิดอะไรขึ้นถ้าคุณแทนที่ 'let' ด้วย 'var'
ZunTzu

มันให้ข้อผิดพลาดเดียวกัน
Cezar

1
มันเป็นเมล็ดพันธุ์แรกสงบลง :) หากหนังสือแจ้งว่ารองรับ แต่ยังไม่มีจำหน่ายก็จะเป็นเช่นนั้น แม้ข้อผิดพลาดกล่าวว่า"ยัง"
akashivskyy

1
ใช่ @akashivskyy คุณมีเหตุผล แต่อาจเป็นได้และมีข้อผิดพลาดในด้านของฉันและมีคนมีวิธีแก้ไขพฤติกรรมนี้ ...
Vincent Saluzzo

1
แอปเปิ้ล @lespommes มีชื่อเสียงเกี่ยวกับทุกสิ่งที่รอดำเนินการ เป็นเรื่องน่าอายสำหรับพวกเขาที่ขาดคุณสมบัติมาตรฐานและชัดเจนเช่นนี้จากการเปิดตัวภาษาหลักรุ่นใหม่ ต้องมีการปรับปรุงหลายอย่างก่อนที่ Swift จะพร้อมใช้งานอย่างจริงจัง
Hyperbole

คำตอบ:


37

ตอนนี้ Swift รองรับตัวแปรคงที่ในคลาสแล้ว สิ่งนี้ไม่เหมือนกับตัวแปรคลาส (เนื่องจากไม่ได้รับการสืบทอดจากคลาสย่อย) แต่ทำให้คุณเข้าใกล้ได้ดี:

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
อย่างที่ Bill บอกว่าไม่เหมือนกัน แต่ที่ฉันต้องการ!
Vincent Saluzzo

@VincentSaluzzo, (และ Bill) อะไรคือความแตกต่างระหว่างตัวแปรนี้กับคลาส?
skywinder

เอกสารของ Apple ได้เปลี่ยนสถานะการอัปเดตเมื่อเร็ว ๆ นี้: developer.apple.com/library/ios/documentation/Swift/Conceptual/… ในความเป็นจริงclassคำสำคัญสามารถใช้สำหรับคุณสมบัติที่คำนวณได้ในขณะนี้เท่านั้นและสแตติกใช้สำหรับคุณสมบัติประเภททั้งหมด (ใน enum คลาส หรือโครงสร้าง)
Vincent Saluzzo

@skywinder ดังที่ฉันได้กล่าวไว้ในคำตอบของฉันตัวแปรคลาสที่แท้จริงสามารถสืบทอดได้โดยคลาสย่อย ตัวแปรคงไม่สามารถ
บิล

@VincentSaluzzo Apple อัปเดตเอกสารหรือไม่ developer.apple.com/library/ios/documentation/Swift/Conceptual/…ดูย่อหน้าที่สี่: "สำหรับชนิดค่า (นั่นคือโครงสร้างและการแจงนับ) คุณสามารถกำหนดคุณสมบัติประเภทที่จัดเก็บและคำนวณสำหรับคลาสคุณสามารถ กำหนดคุณสมบัติประเภทที่คำนวณเท่านั้น "
fujianjin6471

73

การฝังโครงสร้างสามารถใช้งานได้ดีในฐานะวิธีแก้ปัญหา:

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 }
  }
}

จากนั้นคุณสมบัติ SomeClass.workaroundClassVariable ประเภทที่คำนวณได้ราวกับว่าเป็นคุณสมบัติชนิดที่เก็บไว้


1
ทำงานให้ฉัน - ยกเว้นฉันต้องปล่อย 'สาธารณะ' เนื่องจาก XCode 6.0 ไม่ชอบให้ฉันประกาศคลาสสาธารณะภายในคลาสภายใน
Ali Beadle

ใช้งานได้ดียกเว้นว่า xcode ไม่อนุญาตให้มีประเภทซ้อนกันในประเภททั่วไป ... ดังนั้นหากคุณมีคลาสทั่วไปดูเหมือนว่าจะค่อนข้างสิ้นหวังเนื่องจากคุณสมบัติที่คำนวณเท่านั้นที่เป็นไปได้
BenMQ

19

ดูเหมือนว่าจะเป็นไปได้ที่จะประกาศตัวแปรที่มีระยะเวลาการจัดเก็บแบบคงที่ในขอบเขตไฟล์ (เช่นใน C)

var sharedInstance: SplitViewController? = nil

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

อืมทำไมไม่ แต่การกำหนด var ที่ขอบเขตไฟล์ไม่ทำให้หน่วยความจำรั่วไหลในการใช้งานเป็นเวลานาน?
Vincent Saluzzo

@VincentSaluzzo ไม่มีความแตกต่างกับสิ่งที่คุณทำก่อน Swift: เก็บอินสแตนซ์เดียวในตัวแปรคงที่ ไม่มีอะไรจะรั่วไหลที่นี่ยกเว้นอินสแตนซ์เดียวที่ใช้งานได้นานพอ ๆ กับกระบวนการ
Nikolai Ruhe

ฉันลองสิ่งนี้ในสนามเด็กเล่นกับชั้นเรียนของฉันเอง มันไม่ทำงานเพราะยังไม่ได้ประกาศคลาสเมื่อคุณเริ่มต้นตัวแปร "คงที่" ฉันไม่ได้ลองในโครงการ Xcode (ฉันเดาว่ามันต้องใช้งานได้ที่นั่น?) ดังนั้นฉันอาจต้องหา "การประกาศไปข้างหน้าชั้นเรียน" เหมือนที่คุณเคยทำเมื่อระบุโปรโตคอลสำหรับคลาส
kawingkelvin

2
โปรดสังเกตว่าใน Xcode 6.0 privateคุณไม่สามารถมีสองตัวแปรขอบเขตไฟล์ที่มีชื่อเดียวกันแม้ว่าพวกเขาจะ
nschum

@NikolayTsenkov แน่นอน
Nikolai Ruhe

14

วิธีที่ฉันต้องการคือใช้ขอบเขตไฟล์ส่วนตัว var นอกคลาสจากนั้นใช้ class / static getters และ setters:

private var _classVar: Int = 0;

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

5

ตั้งแต่ Swift 1.2 (พร้อมใช้งานกับ Xcode 6.3b1 เป็นต้นไป) staticคุณสมบัติคลาสและวิธีการได้รับการสนับสนุน

class SomeClass
{
    static var someVariable: Int = 0
}

1
คุณทราบหรือไม่ว่าพวกเขาเพิ่งเลิกใช้งานclassตัวแปรหรือมีความแตกต่าง (เคยเป็นstaticสำหรับโครงสร้างclassสำหรับคลาส)
Chris Conover

@chrisco รัฐบันทึกประจำรุ่นว่าเป็นนามแฝงสำหรับstatic class final
Andreas Ley


4

โซลูชันที่คล้ายกับ var ในขอบเขตไฟล์ แต่สามารถปรับแต่งได้มากกว่าและอยู่ใกล้ซิงเกิลตันคือการใช้โครงสร้างที่รองรับ static var เป็นคุณสมบัติของคลาส

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

ตกลงกับวิธีแก้ปัญหาของ Nikolai ที่ได้ผล ฉันโพสต์การเปลี่ยนแปลงของฉันในชุดข้อความนี้เพื่อดูข้อมูล

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
    }
}

และตัวอย่างเช่นใน appDelegate ของฉันฉันสามารถเข้าถึงวิธีการคงที่เช่นนี้

SplitViewController.sharedInstance()!.presentsWithGesture = false

ฉันแค่อยากรู้ แต่ตัวแปร "อินสแตนซ์" ไม่ใช่ตัวแปรสากลหรือ นี่หมายความว่าถ้าคุณมีคลาสซิงเกิลตันอื่นตัวแปร "อินสแตนซ์" ของคุณจะถูกเขียนทับใช่ไหม?
Raphael

1

ข้อความในข้อผิดพลาดมีนัยอย่างมากว่านี่จะเป็นคุณลักษณะของภาษาในอนาคต

คุณอาจต้องการใช้การประกาศตัวแปรคุณสมบัติใน Application Delegate ชั่วคราวและดึงข้อมูลจากที่นั่น ไม่เหมาะแน่นอนต่อต้านรูปแบบ แต่จะให้คุณเป็นศูนย์กลางในการเรียกคืนUISplitViewControllerเมื่อจำเป็น


ไม่เพราะในกรณีของฉัน SplitViewController เริ่มต้นโดยรันไทม์เมื่อตื่นจากกระดานเรื่องราวดังนั้นฉันจึงไม่สามารถเข้าถึงตัวควบคุมมุมมองนี้โดยตรงจากตัวแทนแอปพลิเคชันของฉัน
Vincent Saluzzo

1

คุณต้องรวมตัวแปรคลาสไว้ในตัวแปรโครงสร้างภายใน

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

เรียกว่าType Propertyใน Swift

คุณกำหนดคุณสมบัติชนิดด้วยคีย์เวิร์ดแบบคงที่ สำหรับคุณสมบัติประเภทที่คำนวณสำหรับประเภทคลาสคุณสามารถใช้คีย์เวิร์ดคลาสแทนเพื่ออนุญาตให้คลาสย่อยแทนที่การนำไปใช้งานของซูเปอร์คลาส ตัวอย่างด้านล่างแสดงไวยากรณ์สำหรับคุณสมบัติประเภทที่จัดเก็บและคำนวณ:

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
    }
}

อ่านรายละเอียดเพิ่มเติมได้ที่ลิงค์ด้านล่าง

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.