доступ к выбранному индексу сегментированного управления из другого контроллера представления

avatar
RAS98
8 августа 2021 в 19:28
339
3
0

Я работаю над приложением, которое в настоящее время имеет 2 контроллера представления. Во втором контроллере представления (который я использую для настроек) я использую элемент управления сегментом, чтобы определить сложность игры. Целью настроек viewcontroller является внесение изменений в основные метки viewcontroller. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу найти способ перенести выбранное значение индекса элемента управления сегментом из второго контроллера представления в основной.

вот контроллер просмотра экрана настроек:

    public class SettingsScreen: UIViewController {
    
    @IBOutlet weak var levelPick: UISegmentedControl! // need to use this
    @IBOutlet weak var operationPick: UISegmentedControl!
    
    public override func viewDidLoad() {
        super.viewDidLoad()

    }   
 }

и основной:

    class MainScreen: UIViewController {
       
       @IBOutlet weak var displayText: UILabel!

       
       public override func viewDidLoad() {
           super.viewDidLoad()

       }
       
       
      // how it should work:

      func setLevel() {
           switch SettingsScreen().levelPick.selectedSegmentIndex {
           // easy
           case 0:
               displaytext.text = "test1"
           // medium
           case 1:
               displaytext.text = "test2"
           // hard
           case 2:
               displaytext.text = "test3"
           default:
               break
           }

       }

       @IBAction func Roll(_ sender: UIButton) {
           setLevel()
       } 
   }
Источник
aheze
8 августа 2021 в 19:38
1

Проверьте это: programmingios.net/dont-make-a-new-instance-by-mistake

app4g
9 августа 2021 в 09:55
0

Как насчет обновления изменений в переменной UserDefault и доступа к ней.

RAS98
9 августа 2021 в 10:25
0

@myjunk Как именно? Весь смысл моего поста в том, что я не могу найти правильный способ доступа к переменным из второго контроллера представления.

app4g
9 августа 2021 в 12:24
0

На самом деле это зависит от того, как вы создаете свое приложение, существует множество способов передать переменные во второй VC, некоторые из них сложнее, чем большинство, а некоторые просты. Из вашего примера кода, возможно, можно использовать что-то простое, я опубликовал пример ответа, который вы можете использовать.

Ответы (3)

avatar
app4g
9 августа 2021 в 12:23
0

Поскольку вы имеете в виду ссылку на пользователя, указанного SegmentedIndex на основе некоторых изменений настроек, вы можете использовать UserDefaults для сохранения этого индекса для последующего извлечения. Это было бы проще, но это также зависит от того, что вы на самом деле хотите.

public class SettingsScreen: UIViewController {

@IBOutlet weak var levelPick: UISegmentedControl! // need to use this
@IBOutlet weak var operationPick: UISegmentedControl!

public override func viewDidLoad() {
    super.viewDidLoad()

}   


  @IBAction func levelPickPressed(_ sender: UISegmentedControl) {
    switch levelPick.selectedSegmentIndex {
      case 0:        // Easy
        defaults.set(0, forKey: "levelPick_Level")
        
      case 1:        // Med
        defaults.set(1, forKey: "levelPick_Level")
        
      case 2:       // Hard
        defaults.set(2, forKey: "levelPick_Level")

      default:
        break
      }
   }
}

Затем в коде MainScreen

  func setLevel() {
       levelPick = UserDefaults.standard.integer(forKey: "levelPick_Level")
       switch levelPick {
       // easy
       case 0:
           displaytext.text = "test1"
       // medium
       case 1:
           displaytext.text = "test2"
       // hard
       case 2:
           displaytext.text = "test3"
       default:
           break
       }
   }
RAS98
9 августа 2021 в 17:49
0

что вы имели в виду под этой строкой - defaults.set(0, forKey: "levelPick_Level")? Я изменил его на levelPick.setValue(0, forKey: "levelPick_Level"), и он работает, но вылетает, как только я выбираю другой индекс

app4g
10 августа 2021 в 02:14
0

почему вы не использовали defaults.set(0, forKey: "levelPick_Level"), это не работает? Это настройка userDefaults для сохранения выбранного пользователем selectedSegmentIndex Надеюсь, вы хотя бы погуглили (learnappmaking.com/…) кстати - setValue(_:forKey) предназначен для словаря ключ: значение (developer.apple.com/documentation/objectivec/nsobject/…)

RAS98
10 августа 2021 в 02:35
0

Эй, большое спасибо за попытку помочь. Наконец-то мне удалось сделать это правильно. В конце концов я использовал Segues для передачи переменных из одного контроллера представления в другой.

avatar
Tadreik
9 августа 2021 в 08:14
0

Попробуйте другой подход. Вместо того, чтобы пытаться выяснить выбранный индекс в вашем основном контроллере, вы можете напрямую обновить метки основного контроллера из контроллера настроек. Для этого можно использовать NSNotification.

В главном контроллере viewDidLoad:

NotificationCenter.default.addObserver(forName: NSNotification.Name("notification1"), object: nil, queue: nil) { _ in
    self.myFunction // basically update labels and call your self.present() here
}

В контроллере настроек в событии изменения значения вашего UISegmentedControl:

override func viewDidLoad() {
    super.viewDidLoad()
    mySegmentedControl.addTarget(self, action: #selector(function), for: .valueChanged)
}

@objc func function() {
    NotificationCenter.default.post(name: NSNotification.Name("notification1"), object: nil)
}
RAS98
9 августа 2021 в 11:36
0

Я хочу обновить метки с помощью кнопки Roll внутри основного контроллера просмотра. Как я могу этого добиться? Также что вы подразумеваете под self.present() ?

avatar
Ahmad Yasser Alshalabi
8 августа 2021 в 22:11
0

Вы можете использовать шаблон делегата или шаблон обратного вызова закрытия. вот так:

** Экран настроек:**

class SettingsViewController: UIViewController {

    var segmentIndex: Int = 0
    
    var closure: ((_ segmentIndex: Int) -> ())?
    
    @IBOutlet weak var levelPick: UISegmentedControl!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.levelPick.selectedSegmentIndex = self.segmentIndex

    }
    
    @IBAction func levelPickAction(_ sender: Any) {
        
        guard let closure = self.closure else {
            return
        }
        closure(levelPick.selectedSegmentIndex)
    }
    
}

** Главный экран:**

    class MainViewController: UIViewController {

    var segmentIndex: Int = 0

    @IBOutlet weak var displayText: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

    }
    
    @IBAction func Roll(_ sender: Any) {
        
        let vc = (UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SettingsViewController") as! SettingsViewController)
        vc.segmentIndex = segmentIndex
        vc.closure = { [weak self] segmentIndex in
            self!.segmentIndex = segmentIndex
            switch segmentIndex {
            // easy
            case 0:
                self!.displayText.text = "test1"
            // medium
            case 1:
                self!.displayText.text = "test2"
            // hard
            case 2:
                self!.displayText.text = "test3"
            default:
               break
            }
        }
        self.present(vc, animated: true, completion: nil)
    
    }
    
}
RAS98
8 августа 2021 в 23:22
0

Привет. ну больше не вылетает, но и ничего не меняет, типа кода просто нет. Кроме того, выбранный индекс на экране настроек сбрасывается каждый раз, когда я переключаюсь на главный экран.

Ahmad Yasser Alshalabi
8 августа 2021 в 23:44
0

@Roei, ты прав. Я добавил переменную segmentIndex в оба ViewController. проверить это.

RAS98
9 августа 2021 в 00:00
0

Все равно не работает, ничего не изменилось. Кстати, я очень ценю вашу помощь!

Ahmad Yasser Alshalabi
9 августа 2021 в 00:21
0

@Roei Посмотрите этот проект: github.com/AhmadYasserAlshalabi/ClosureCallback