2015-08-28 40 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。 –