UISwitch已被用户关闭但仍以编程方式

时间:2016-03-17 02:48:12

标签: ios swift uiswitch

我正在使用Swift在xcode上试验UISwitches。我有它有几个公司名称及其相应的开关。从上到下,如果用户切换例如“Google”开启,则他们可以查看所选公司的facebook和twitter。如果他们选择其他公司,一旦他们打开该开关,例如“三星”,谷歌开关关闭,然后用户可以看到三星的Facebook和Twitter页面。

我的问题是......从上到下,它运作正常。我能看到从谷歌到三星的两个页面。但是,如果我从三星回到谷歌,谷歌开关打开,但它仍然显示三星的页面。但是,如果我打开saumsung开关,关闭然后转到谷歌,它工作正常。

我的假设是,当一个开关从底部到顶部打开另一个开关时,视觉上看起来很开,但它仍然是以编程方式开启的

我想知道人们是否有过类似的问题。如果没有,我希望如果他们发现自己处于类似情况,这对未来有帮助

这是我的主视图Controller

import UIKit

   class ViewController: UIViewController {

@IBOutlet weak var GoogleSwitch: UISwitch!
@IBOutlet weak var SamsungSwitch: UISwitch!
@IBOutlet weak var FordSwitch: UISwitch!
@IBOutlet weak var ToyotaSwitch: UISwitch!
@IBOutlet weak var SquareEnixSwitch: UISwitch!
@IBOutlet weak var ABCBankSwitch: UISwitch!

var Google: Bool = false
var Samsung: Bool = false
var Ford: Bool = false
var Toyota:Bool = false
var SquareEnix :Bool = false
var ABCBank :Bool = false

override func viewDidLoad() {
    super.viewDidLoad()
 //   ABCBankSwitch.addTarget(self, action: Selector("switchIsChanged:"), forControlEvents: UIControlEvents.ValueChanged)
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func ActiveGoogle(sender: UISwitch) {

      if sender.on == true
        {
            GoogleSwitch.on = true
            SamsungSwitch.on = false
            ToyotaSwitch.on = false
            SquareEnixSwitch.on = false
            ABCBankSwitch.on = false
            Google = true

   // GoogleSwitch.on = true


    }
  else
   { Google = false
    sender.on = false
    }

   // sender.on  = false
}

@IBAction func ActiveSamsung(sender: UISwitch) {

 if sender.on == true
      {
            GoogleSwitch.on = false
            SamsungSwitch.on = true
            FordSwitch.on = false
            ToyotaSwitch.on = false
            SquareEnixSwitch.on = false
            ABCBankSwitch.on = false
            Samsung = true

    }
   else

    {sender.on = false
        Samsung = false}

}

@IBAction func ActiveFord(sender: UISwitch) {
  if sender.on == true
    {Ford = true
        GoogleSwitch.on = false
        SamsungSwitch.on = false
        FordSwitch.on  = true
        ToyotaSwitch.on = false
        SquareEnixSwitch.on = false
        ABCBankSwitch.on = false
    }
   else
  { if sender.on == false {
    Ford = false}

}
}

@IBAction func ActiveToyota(sender: UISwitch) {
   if sender.on == true
    { Toyota = true
        GoogleSwitch.on = false
        SamsungSwitch.on = false
        FordSwitch.on = false
        ToyotaSwitch.on = true
        SquareEnixSwitch.on = false
        ABCBankSwitch.on = false
    }
    else
    { Toyota = false}
}
@IBAction func ActiveEnix(sender: UISwitch) {
if sender.on == true
    { SquareEnix = true
        GoogleSwitch.on = false
        SamsungSwitch.on = false
        FordSwitch.on = false
        ToyotaSwitch.on = false
        //SquareEnixSwitch.on = true
        ABCBankSwitch.on = false
    }
    else
    { SquareEnix = false
   // sender.on = false
    }
}

@IBAction func ActiveABC(sender: UISwitch) {
  if sender.on == true
    { ABCBank = true
        ABCBankSwitch.setOn(true, animated: true)
        GoogleSwitch.on = false
        SamsungSwitch.on = false
        FordSwitch.on = false
        ToyotaSwitch.on = false
        SquareEnixSwitch.on = false


        }
    }
else
{
    ABCBankSwitch.setOn(false, animated: true)
    ABCBank = false
   // sender.on = false

  }

}

}

这是我的FacebookViewController。 (不要把Twitter打开,因为它几乎与facebook的相同)

 import UIKit

 class FacebookViewController: UIViewController{
  var webAddress: String = ""

@IBOutlet weak var CompanyFB: UIWebView!

override func viewWillAppear(animated: Bool) {
    let myCompany: ViewController = self.tabBarController!.viewControllers![0] as! ViewController

    let showGoogle: Bool = myCompany.Google
    let showSamsung: Bool = myCompany.Samsung
    let showFord: Bool = myCompany.Ford
    let showToyota: Bool = myCompany.Toyota
    let showEnix: Bool = myCompany.SquareEnix
    let showBank:Bool = myCompany.ABCBank


    if showGoogle  {
        webAddress = "https://www.facebook.com/Google/"
        //myCompany.GoogleSwitch.on = false  had this to test. either way is still doesnt work

      //  CompanyFB.loadRequest(NSURLRequest(URL: NSURL(string: webAddress)!))
    }

    if showSamsung  {
        webAddress = "https://www.facebook.com/SamsungUSA"
       // myCompany.SamsungSwitch.on = false

      //  CompanyFB.loadRequest(NSURLRequest(URL: NSURL(string: webAddress)!))
    }

     if showFord  {
        webAddress = "https://www.facebook.com/ford/"

      //  CompanyFB.loadRequest(NSURLRequest(URL: NSURL(string: webAddress)!))
    }

    if showToyota {
        webAddress = "https://www.facebook.com/toyota"


       // CompanyFB.loadRequest(NSURLRequest(URL: NSURL(string: webAddress)!))
    }
   if  showEnix  {
       webAddress = "https://www.facebook.com/SquareEnix"

    }

 if showBank  {
        webAddress = "https://www.facebook.com/ABC-Bank-132047286857188/"


    }

 CompanyFB.loadRequest(NSURLRequest(URL: NSURL(string: webAddress)!))


}


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

3 个答案:

答案 0 :(得分:2)

您的问题是,您没有将单独的布尔与您的交换机保持同步。请考虑以下代码:

@IBAction func ActiveGoogle(sender: UISwitch) {    
    if sender.on == true {
        GoogleSwitch.on = true
        SamsungSwitch.on = false
        ToyotaSwitch.on = false
        SquareEnixSwitch.on = false
        ABCBankSwitch.on = false
        Google = true
    }
    else { 
        Google = false
        sender.on = false
    }
}

如果我更改“Google”切换,那么Google变量将相应地设置为true / false。此代码还会关闭所有其他开关,但不会更改布尔关联变量。因此,如果在选择Google I然后选择“Samsung”后,Google开关将关闭,但Google变量仍然为真。

您可以使用计算属性而不是单独的布尔值:

var Google: Bool {
    return self.GoogleSwitch.on
}

等等。

此外,按惯例,变量和函数应以小写字母开头,因此它应为var googlefunc activateGoogle

答案 1 :(得分:1)

这里有一些事情,有些事情与你的问题无关,但我也会评论它们,所以你可以改进编码器。

1)Swift的约定规定您命名以小写字母开头的变量和方法。因此,GoogleSwitch应为googleSwitch等。另外,请尝试使用名称进行描述。在FacebookViewController myCompany类中,您有一个变量ViewController。首先,应该调用类MyCompanyViewController之类的内容,以便知道它是哪个视图控制器。然后myCompany变量可以称为myCompanyViewControllerCompanyFB应该是companyFBWebView

2)你可以在这里简单地编写代码。对所有交换机使用单个IBAction。一个常见问题(这可能是一个问题),当您在Interface Builder中复制和粘贴控件时,它有时会复制分配的操作,然后您添加另一个,因此每次切换时都会调用两个方法。通过使用单一方法,您可以节省大量重复的代码并避免此问题。

您的整个第一个ViewController课程可以缩小为此(然后将所有开关连接到同一个IBOutlet switchToggled:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var googleSwitch: UISwitch!
    @IBOutlet weak var samsungSwitch: UISwitch!
    @IBOutlet weak var fordSwitch: UISwitch!
    @IBOutlet weak var toyotaSwitch: UISwitch!
    @IBOutlet weak var squareEnixSwitch: UISwitch!
    @IBOutlet weak var abcBankSwitch: UISwitch!

    @IBAction func switchToggled(sender: UISwitch) {
        // Remember the state of the triggered switch because we're about to turn it off
        let newState: Bool = sender.on

        googleSwitch.on = false
        samsungSwitch.on = false
        fordSwitch.on = false
        toyotaSwitch.on = false
        squareEnixSwitch.on = false
        abcBankSwitch.on = false

        // Restore the state of the switch
        sender.on = newState
    }
}

3)避免对同一件事使用重复变量,Bool for Google等应该与交换机相同,所以只需使用switch.on值即可。编辑:(或Paulw11提到的,使用计算属性)。

4)当使用if来测试变量状态,或者在FacebookViewController类中使用多个变量状态时,如果只发生一种可能的情况,请使用{{1}而不是多个else if的。在您的情况下,您一次触发两个或更多个案件(由于您的其他错误)。如果你使用了if条款,那么你只会触发一个条款,而你可能会早些时候缩小你的其他bug。

else if

5)扩展#4你可以改变它以利用Swift强大的 if showGoogle { webAddress = "https://www.facebook.com/Google/" } else if showSamsung { webAddress = "https://www.facebook.com/SamsungUSA/" } ... 功能。

enum

6)在Swift中,避免像瘟疫那样使用import UIKit class FacebookViewController: UIViewController { enum Company: String { case Google = "https://www.facebook.com/Google/" case Samsung = "https://www.facebook.com/SamsungUSA/" case Ford = "https://www.facebook.com/ford/" case Toyota = "https://www.facebook.com/toyota/" case SquareEnix = "https://www.facebook.com/SquareEnix/" case ABCBank = "https://www.facebook.com/ABC-Bank-132047286857188/" } var company: Company = .Google // Default to Google @IBOutlet weak var companyFBWebView: UIWebView! override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let myCompanyViewController: ViewController = self.tabBarController!.viewControllers![0] as! ViewController if myCompanyViewController.googleSwitch.on { company = .Google } else if myCompanyViewController.samsungSwitch.on { company = .Samsung } else if myCompanyViewController.fordSwitch.on { company = .Ford } else if myCompanyViewController.toyotaSwitch.on { company = .Toyota } else if myCompanyViewController.squareEnixSwitch.on { company = .SquareEnix } else if myCompanyViewController.abcBankSwitch.on { company = .ABCBank } if let url = NSURLRequest(URL: NSURL(string: company.rawValue)) { companyFBWebView.loadRequest(url) } } } 。理想情况下,您只会将其用于!以及您知道某些值存在的其他情况。在某些情况下,行IBOutlet可能会崩溃。可能是由于时间问题或您可能对代码进行的其他更改。更安全地使用let myCompanyViewController: ViewController = self.tabBarController!.viewControllers![0] as! ViewController检查选项并优雅地处理错误。

7)我刚刚注意到另一个问题,因为我正在校对。任何时候*你if let来自超类的方法,请确保你也调用超级版本。因此,您的override等电话需要调用超级版本,否则您可能会变得非常奇怪,难以追踪错误。

  • 我在#7的Anytime上放了一颗星,因为在某些情况下你有意不想调用超级方法,但这些很少见,你会在时机成熟时知道它。

答案 2 :(得分:0)

我假设您的IBActions与ValueChanged事件挂钩,并且您希望它们在两个实例中触发:当您通过触摸它来更改开关时;或者当您更改on属性的值时。

如果是这样,问题是事件不会在第二种情况下触发,只触发第一种情况。因此,一旦Google设置为true,将其设置为false的唯一方法是将开关触摸为关闭。

由于您的模型只需要打开一个开关,因此您可以使用一个包含应该打开的开关的变量。当您触摸开关时,只需更新该变量并重新显示所有变量即可。对此变量使用enum会很有帮助。沿着:

    enum Switches {
        case None
        case Google
        case Samsung
    }

    var onSwitch = Switches.None

然后在每个IBAction中编写代码:

@IBAction func ActiveGoogle(sender: UISwitch) {
      if sender.on == true {
          onSwitch = Switches.Google
          updateSwitches()
      }
}

updateSwitches看起来像:

func updateSwitches() {
    GoogleSwitch.on = (onSwitch == Switches.Google)
    SamsungSwitch.on = (onSwitch == Switches.Samsung)
}