2014-10-08 18 views
15

Khi tôi tạo ra một setter như ví dụ:Tạo Một Setter Chỉ Trong Swift

var masterFrame:CGRect{ 
     set{ 
      _imageView.frame = newValue 
      _scrollView.frame = newValue 
     } 
    } 

nó buộc tôi phải làm một getter, mà tôi không muốn làm.

Có cách nào để tạo trình thiết lập trong Swift mà không có bộ khởi động không?

+2

Nope - âm thanh như bạn muốn được tốt hơn off với một phương pháp. –

+0

Hmm Tôi cho rằng đây là điều duy nhất tôi sẽ ghét ngay sau đó! – Aggressor

+2

Khi nào bạn sử dụng các thuộc tính chỉ ghi? Tôi chưa bao giờ có dịp làm như vậy. –

Trả lời

3

Thuộc tính chỉ thiết lập không có vẻ như nó có ý nghĩa rất nhiều. Bạn có lẽ nên sử dụng một phương pháp cho rằng thay vào đó.

Hoặc, chỉ cần thực hiện biên dịch hạnh phúc và thêm một getter mà bạn không bao giờ gọi:

get { 
    return _imageView.frame 
} 
+0

Đó là giải pháp hiện tại của tôi nhưng tôi ước tôi cũng không có: ( – Aggressor

+3

) Bạn cũng có thể đặt '' 'didSet''' trên khung của imageView để cập nhật scrollView's Hoặc sử dụng AutoLayout với các ràng buộc để làm cho chúng bằng nhau –

+0

Các trình cài đặt dành cho thiết lập Các trình theo dõi thuộc tính dành cho các tác vụ thực hiện trước/sau khi một thuộc tính được truy cập. – Andrew

12

Từ docs:

Các getter được sử dụng để đọc các giá trị, và setter được sử dụng để viết giá trị. Mệnh đề setter là tùy chọn, và khi chỉ có một getter là cần thiết, bạn có thể bỏ qua cả hai mệnh đề và chỉ cần trả lại giá trị được yêu cầu trực tiếp, như được mô tả trong thuộc tính chỉ đọc. Nhưng nếu bạn cung cấp điều khoản setter, bạn cũng phải cung cấp điều khoản getter .

+21

Có một cách để giải quyết vấn đề này.Có rất nhiều trường hợp tôi muốn những người định cư không có getters ... – Aggressor

7

Để có một "tài sản setter-only", bạn chỉ có thể có một chức năng đơn giản mà đặt giá trị; ví dụ, nếu chúng ta có một sở hữu tư nhân được gọi là value, chúng ta có thể có một phương pháp setter gọi, configureWithValue(value:String) rằng cập nhật tài sản nhưng không cho phép truy cập bên ngoài để tài sản:

private var value:String 

func configureWithValue(value:String) { 
    self.value = value 
} 
8

Vâng, nếu tôi thực sự phải, Tôi sẽ sử dụng cái này.

public subscript(index: Int) -> T { 
    get { 
     fatalError("You cannot read from this object.") 
    } 
    set(v) { 
    } 
} 

Điều này được kiểm tra trong thời gian chạy, nhưng sẽ phân phối rõ ràng ý định của bạn cho người dùng mã.

Sẽ rất tuyệt nếu trình biên dịch Swift hỗ trợ một số thuộc tính trên getters.

public subscript(index: Int) -> T { 
    @availability(*,unavailable) 
    get { 
     fatalError("You cannot read from this object.") 
    } 
    set(v) { 
    } 
} 

Nhưng điều này không hiện đang làm việc: P (Swift 1.2, phiên bản 6.3.1 (6D1002))

Cách nhanh nhất và dễ nhất sẽ được yêu cầu này trên Apple Radar và Apple Developer Forum.

3

Chắc chắn. Bạn chỉ có thể trả về một con số không và làm cho các loại tùy chọn:

var color: MyColorEnum? { 
    get { return nil } 
    set { 
     switch newValue! { 
     case .Blue: 
     view.backgroundColor = UIColor.blueColor() 
     case .Red: 
     view.backgroundColor = UIColor.redColor() 
     } 
    } 
    } 

Ngoài ra, bạn có thể sử dụng didSet để tránh những vấn đề tất cả cùng nhau:

var color: MyColorEnum! { 
    didSet { 
    switch color { 
     case .Blue: 
     view.backgroundColor = UIColor.blueColor() 
     case .Red: 
     view.backgroundColor = UIColor.redColor() 
     } 
    } 
} 
0

Bạn có thể trở nil từ get:

var input: CGRect? { 
    set(value) { 
     guard let value = value else { return } 
     // process the value here 
    } 
    get { 
     return nil 
    } 
} 
0

Tôi đã tìm thấy một ngoại lệ mà tôi thực sự thích một biến chỉ setter đó là khi tôi đi qua một đóng cửa là tham số duy nhất trong một metho d cho mục đích duy nhất là lưu nó để thực hiện sau này.

tôi thực hiện nó như một phương pháp như sau:

typealias ThemeSetter =() ->() 

class Theme { 

    fileprivate var themeSetters:[ThemeSetter] = [] 

    class var shared: Theme { 
     struct Singleton { 
      static let instance = Theme() 
     } 
     return Singleton.instance 
    } 
     ... 

    func setColor(_ entry:@escaping ThemeSetter) { 
     entry() 
     themeSetters.append(entry) 
    } 
} 

Sau đó tôi có thể gọi phương thức như sau:

Theme.shared.setColor({ 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    }) 

Nhưng tôi không thích paretheses gần sau khung chặt chẽ, kể từ Tôi có thể có nhiều dòng trong việc đóng cửa.

Vì vậy, biết về Trailing đóng cửa Tôi chỉ có thể thay đổi mã để trông như thế này:

Theme.shared.setColor() { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

này là hoàn toàn ổn và là cú pháp mà Apple cho thấy cho Trailing đóng cửa. Kể từ khi có chỉ là một tham số và là tối giản rằng tôi Tôi bị cám dỗ để làm cho đoạn code thậm chí gọn nhẹ hơn và giảm nó như thế này:

Theme.shared.setColor { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

Đó là một lần nữa làm thế nào Apple cho thấy để làm Trailing đóng cửa; Ngoại trừ, cách này thường được sử dụng cho một số loại Predicate nơi đóng cửa được sử dụng để nói cho phương pháp làm thế nào để làm một loại hoặc khi đóng cửa được sử dụng ở phần cuối của một cuộc gọi chức năng không đồng bộ như là một đóng cửa hoàn thành. Những gì tôi muốn là gán cho việc đóng cửa ... Cái gì đó.

Nếu tôi thay thế các phương pháp để setcolor với một biến nó trông như thế này:

var setColor:ThemeSetter? { 
     didSet { 
      if setColor != nil { 
       setColor?() 
       themeSetters.append(setColor!) 
       setColor = nil 
      } 
     } 
    } 

Bây giờ cuộc gọi như sau:

Theme.shared.setColor = { 
     self.navigationBar.barTintColor = Theme.shared.gameBarTint 
    } 

Đó dấu bằng có nghĩa là tất cả sự khác biệt được. Nó cho thấy rằng tôi đang chỉ định một đóng cửa và không chạy một số chức năng sử dụng đóng cửa, mặc dù nó có. : ') < - cần biểu tượng cảm xúc tại đây.

Ghi chú cuối cùng: Điều này thực sự không liên quan gì đến việc đóng cửa, nó chỉ cho bạn thấy cách bạn có thể tạo biến setter, ngoại trừ việc nó vẫn trả về một số không. Nó không có nghĩa là để bảo vệ lớp khỏi việc người dùng truy cập vào biến để đọc giống như một setter thực sự. Ngoài ra, hãy tha thứ cho hướng dẫn về Trailing Closures và Singletons.

Tôi có thể không nhận được đủ Phiếu bầu để trả lời đúng nhưng tại sao câu trả lời chính xác là "Không, bạn không thể! Bạn phải sử dụng cuộc gọi phương thức!". Tôi nói, "Ni" với điều đó, ai cần tất cả cú pháp đó. Chỉ cần sử dụng một biến và không đọc nó trở lại hoặc nếu bạn làm, không có nó trả lại bất cứ điều gì. giống như câu trả lời của Rudolf Adamkovic, có 0 phiếu bầu.

4

Sử dụng didSet thay vì:

var masterFrame:CGRect { 
     didSet { 
      _imageView.frame = masterFrame 
      _scrollView.frame = masterFrame 
     } 
    } 
Các vấn đề liên quan