2015-08-28 53 views
0

好,所以我想創建一個在Swift編程語言中創建項目符號的類。但是我很難弄清楚如何初始化子彈點的樣式。在Swift類中初始化一個AnyObject屬性?

初始化項目符號點對象後,我希望能夠選擇項目符號點的樣式是否爲導入的圖像,在這種情況下,該屬性將符合UIImageView或(默認情況下)項目符號樣式將成爲一個自動遞增的數字值並符合UILabel

例如,我想這個類的結構看起來是這樣的:

class bullet { 

    var bulletStyle: AnyObject 

    init() { 
     bulletStyle = UILabel() 
    } 

    init(styleImage style:UIImageView) { 
     bulletStyle = style 
    } 
} 

但是測試的類之後,bulletStyle仍承擔類型AnyObject初始化類兩種方式之後。那麼如何在初始化時將bulletStyle設置爲UILabel對象或UIImageView對象?

+0

初始化後,'bulletStyle'確實有UILabel'或'UIImageView'的'的潛在價值,但它的類型是'AnyObject',其中,按照Swift的類型安全功能在聲明變量後不能更改。 – aaplmath

+0

您可以嘗試將對象封裝到自定義類中,而不是使用AnyObject。然後你可以添加邏輯來處理你的用例。 –

+0

@aaplmath正確...但如果我初始化一個新的子彈實例,說:'var newBullet = bullet()',然後我嘗試更改bulletStyle的文本,因爲它初始化爲默認的'UILabel',如: 'newBullet.bulletStyle.text'它不能識別'bulletStyle'具有'.text'屬性並引發錯誤。 – Yonny

回答

0

我建議使用一個協議。你創建一個協議BulletStyle,並且你創建了兩個實現這個協議的類。以下是一個代碼示例。

protocol BulletStyle { 

    var bulletText: String? { get set} 

    var bulletImage: UIImage? { get set} 

} 

class Bullet { 

    var bulletStyle: BulletStyle 

    init() { 
     bulletStyle = BulletLabel() 
    } 

    init(styleImage style:BulletImageView) { 
     bulletStyle = style 
    } 
} 

class BulletLabel: UILabel, BulletStyle { 

    var bulletText: String? { 
     get { 
      return self.text 
     } 
     set { 
      self.text = newValue 
     } 
    } 

    var bulletImage: UIImage? { 
     get { 
      return nil 
     } 
     set { 
      // nothing to set 
     } 
    } 

} 

class BulletImageView: UIImageView, BulletStyle { 

    var bulletText: String? { 
     get { 
      return nil // no text for an image 
     } 
     set { 
      // nothing to set for an image 
     } 
    } 

    var bulletImage: UIImage? { 
     get { 
      return self.image 
     } 
     set { 
      self.image = newValue 
     } 
    } 

} 


class YourApp { 

    var myBullets : [BulletStyle]? 

    func createBullets() { 
     myBullets = [BulletLabel(), BulletLabel(), BulletImageView()] 
     myBullets![0].bulletText = "bulletA" 
     myBullets![1].bulletText = "bulletB" 
     myBullets![2].bulletImage = UIImage(named: "myBulletImageA") 
    } 

} 
+0

這個想法使用符合相同協議的兩個子類是聲音,但不是這樣。整個協議應該與兩個班級相關,而不是一個班級的一半,另一個班級的另一半。想想子彈在邏輯層面上需要什麼外部接口,並確保這兩個項目符號類以相關的方式實現它。 – fishinear

+0

感謝您的評論。我不同意協議有任何問題。這完全是關於協議的語義。協議是這樣的合同:「需要BulletStyle實現來指定它是否有文本,如果沒有,則實現必須返回nil」。圖像相同。這個合同對於這兩個類都是相關的。我可以用另一個同時具有圖像和文本的BulletStyle實現來擴展該示例。不過,我確實同意這個例子可以通過採用大小或indentationLevel等通用屬性來簡化。 –

0

感謝大家的評論和回覆。我原本希望有一種方法來改變變量類型,但現在意識到這是絕對不鼓勵的,並且違背了Swift自己的類型安全特性。

想要更改變量類型的原因是因爲我想在所有項目符號對象的屬性上創建自動佈局約束。我知道這是因爲UIImageViewUILabel都是從UIView繼承的,根據情況初步確定和設置一個變量會容易得多,這樣我就只需要擔心創建一個集合NSLayoutConstraint's,使用那一個變量。

無論如何,我回答了我自己的問題,並決定最好的解決方案是創建一個額外的UIView對象作爲每個案件的容器。我仍然只使用一個變量和一組NSLayoutConstraint來設置容器是否應該容納UIImageViewUILabel。此外,通過這樣做,今後我可以使用單個容器對象來獲得所需的附加約束。

這裏是什麼樣子:

class bullet { 

    var bulletStyleContainer: UIView 

    init(bulletStyle: AnyObject) { 

     bulletStyleContainer = UIView() 
     createBulletStyle(bulletStyle) 
    } 

    func createBulletStyle(style: AnyObject) { 

     if style is UIImageView { 

      bulletStyleContainer.addSubview(style as! UIImageView) 

     } else if style is UILabel { 

      bulletStyleContainer.addSubview(style as! UILabel) 

     } else { 

      let style = style as! UIView 
      style.backgroundColor = UIColor.blackColor() 
      bulletStyleContainer.addSubview(style) 

     } 

     let leftPinConstraint = NSLayoutConstraint(item: style, attribute: .Leading, relatedBy: .Equal, toItem: bulletStyleContainer, attribute: .Leading, multiplier: 1.0, constant: 0) 
     let rightPinConstraint = NSLayoutConstraint(item: bulletStyleContainer, attribute: .Trailing, relatedBy: .Equal, toItem: style, attribute: .Trailing, multiplier: 1.0, constant: 0) 
     let topPinConstraint = NSLayoutConstraint(item: style, attribute: .Top, relatedBy: .Equal, toItem: bulletStyleContainer, attribute: .Top, multiplier: 1.0, constant: 0) 
     let bottomPinConstraint = NSLayoutConstraint(item: bulletStyleContainer, attribute: .Bottom, relatedBy: .Equal, toItem: style, attribute: .Bottom, multiplier: 1.0, constant: 0) 

     style.setTranslatesAutoresizingMaskIntoConstraints(false) 
     NSLayoutConstraint.activateConstraints([leftPinConstraint,rightPinConstraint,topPinConstraint,bottomPinConstraint]) 

    } 
+0

我仍然認爲@Peter提出用一個通用協議創建兩個子彈類將是一個更好的解決方案。其中一個子彈類派生自UILabel,另一個來自UIImage,以滿足您對約束的需求。 – fishinear

+0

如果您至少選擇這種方法,我建議您將bulletStyle的類型更改爲UIView。 –