Сделайте сегментированный контроль, измените значение для другого VC [duplicate]

Math.sum (javascript) .... вид замещения оператора

.1 + .0001 + -.1 --> 0.00010000000000000286
Math.sum(.1 , .0001, -.1) --> 0.0001

Object.defineProperties(Math, {
    sign: {
        value: function (x) {
            return x ? x < 0 ? -1 : 1 : 0;
            }
        },
    precision: {
        value: function (value, precision, type) {
            var v = parseFloat(value), 
                p = Math.max(precision, 0) || 0, 
                t = type || 'round';
            return (Math[t](v * Math.pow(10, p)) / Math.pow(10, p)).toFixed(p);
        }
    },
    scientific_to_num: {  // this is from https://gist.github.com/jiggzson
        value: function (num) {
            //if the number is in scientific notation remove it
            if (/e/i.test(num)) {
                var zero = '0',
                        parts = String(num).toLowerCase().split('e'), //split into coeff and exponent
                        e = parts.pop(), //store the exponential part
                        l = Math.abs(e), //get the number of zeros
                        sign = e / l,
                        coeff_array = parts[0].split('.');
                if (sign === -1) {
                    num = zero + '.' + new Array(l).join(zero) + coeff_array.join('');
                } else {
                    var dec = coeff_array[1];
                    if (dec)
                        l = l - dec.length;
                    num = coeff_array.join('') + new Array(l + 1).join(zero);
                }
            }
            return num;
         }
     }
    get_precision: {
        value: function (number) {
            var arr = Math.scientific_to_num((number + "")).split(".");
            return arr[1] ? arr[1].length : 0;
        }
    },
    diff:{
        value: function(A,B){
            var prec = this.max(this.get_precision(A),this.get_precision(B));
            return +this.precision(A-B,prec);
        }
    },
    sum: {
        value: function () {
            var prec = 0, sum = 0;
            for (var i = 0; i < arguments.length; i++) {
                prec = this.max(prec, this.get_precision(arguments[i]));
                sum += +arguments[i]; // force float to convert strings to number
            }
            return Math.precision(sum, prec);
        }
    }
});

Идея состоит в том, чтобы вместо Math вместо Math использовать ошибки плавания

Math.diff(0.2, 0.11) == 0.09 // true
0.2 - 0.11 == 0.09 // false

также отмечают, что Math.diff и Math.sum автоматически определяют точность использования

. Math.sum принимает любое количество аргументов

69
задан Duncan C 21 February 2016 в 21:01
поделиться

5 ответов

Как отметил @nhgrif в своем превосходном ответе, существует множество способов, которыми VC (контроллеры просмотра) и другие объекты могут связываться друг с другом.

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

Ответ nhrif позволяет отправлять информацию непосредственно из источника в пункт назначения VC. Как я уже упоминал в ответ, также можно отправлять сообщения от адресата к источнику.

Фактически вы можете настроить активный односторонний или двухсторонний канал между различными контроллерами. Если контроллеры представлений связаны через segue раскадровки, время, необходимое для настройки ссылок, находится в методе prepareFor Segue.

У меня есть пример проекта в Github, который использует родительский контроллер представления для размещения 2 разных таблиц как дети. Контроллеры дочерних представлений связаны с использованием встроенных сегментов, а контроллер родительского представления подключает двухсторонние ссылки с каждым контроллером представления в методе prepareForSegue.

Вы можете найти этот проект на github (ссылка). Однако я написал его в Objective-C и не преобразовал его в Swift, поэтому, если вам не удобно в Objective-C, может быть немного трудно следовать

40
ответ дан Duncan C 28 August 2018 в 03:11
поделиться

Swift 4

Существует так много подходов к передаче данных в swift. Здесь я добавляю некоторые из лучших подходов к нему.

1) Использование StoryBoard Segue

Сетчатые раскладки очень полезны для передачи данных между контроллерами Source и Destination View Controllers и наоборот также.

// If you want to pass data from ViewControllerB to ViewControllerA while user tap on back button of ViewControllerB.
        @IBAction func unWindSeague (_ sender : UIStoryboardSegue) {
            if sender.source is ViewControllerB  {
                if let _ = sender.source as? ViewControllerB {
                    self.textLabel.text = "Came from B = B->A , B exited"
                }
            }
        }

// If you want to send data from ViewControllerA to ViewControllerB
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if  segue.destination is ViewControllerB {
                if let vc = segue.destination as? ViewControllerB {
                    vc.dataStr = "Comming from A View Controller"
                }
            }
        }

2) Использование методов делегата

ViewControllerD

//Make the Delegate protocol in Child View Controller (Make the protocol in Class from You want to Send Data)
    protocol  SendDataFromDelegate {
        func sendData(data : String)
    }

    import UIKit

    class ViewControllerD: UIViewController {

        @IBOutlet weak var textLabelD: UILabel!

        var delegate : SendDataFromDelegate?  //Create Delegate Variable for Registering it to pass the data

        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            textLabelD.text = "Child View Controller"
        }

        @IBAction func btnDismissTapped (_ sender : UIButton) {
            textLabelD.text = "Data Sent Successfully to View Controller C using Delegate Approach"
            self.delegate?.sendData(data:textLabelD.text! )
            _ = self.dismiss(animated: true, completion:nil)
        }
    }

ViewControllerC

    import UIKit

    class ViewControllerC: UIViewController , SendDataFromDelegate {

        @IBOutlet weak var textLabelC: UILabel!

        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
        }

        @IBAction func btnPushToViewControllerDTapped( _ sender : UIButton) {
            if let vcD = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerD") as?  ViewControllerD  {
                vcD.delegate = self // Registring Delegate (When View Conteoller D gets Dismiss It can call sendData method
    //            vcD.textLabelD.text = "This is Data Passing by Referenceing View Controller D Text Label." //Data Passing Between View Controllers using Data Passing
                self.present(vcD, animated: true, completion: nil)
            }
        }

        //This Method will called when when viewcontrollerD will dismiss. (You can also say it is a implementation of Protocol Method)
        func sendData(data: String) {
            self.textLabelC.text = data
        }

    }
3
ответ дан iOS Team 28 August 2018 в 03:11
поделиться

Вместо создания контроллера данных контроллера я бы предложил создать экземпляр контроллера данных и передать его. Чтобы поддерживать инъекцию зависимостей, я бы сначала создал протокол DataController:

protocol DataController {
    var someInt : Int {get set} 
    var someString : String {get set}
}

Тогда я бы создал SpecificDataController (или любое другое имя в настоящее время было бы подходящим) class:

class SpecificDataController : DataController {
   var someInt : Int = 5
   var someString : String = "Hello data" 
}

Класс ViewController должен иметь поле для удерживания dataController. Обратите внимание, что тип dataController - это протокол DataController. Таким образом, легко отключить реализации контроллера данных:

class ViewController : UIViewController {
   var dataController : DataController?
   ...
}

В AppDelegate мы можем установить viewController dataController:

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if let viewController = self.window?.rootViewController as? ViewController {
        viewController.dataController =  SpecificDataController()
    }   
    return true
}

. Когда мы переходим к другому viewController мы можем передать dataController в:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    ...   
}

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

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

При таком подходе мы можем разделить вид логической части.

2
ответ дан Kristiina 28 August 2018 в 03:11
поделиться

SWIFT 3:

Если у вас есть раскадровка с идентифицированными выделениями, используйте:

func prepare(for segue: UIStoryboardSegue, sender: Any?)

Хотя, если вы все программно осуществляете навигацию между различными UIViewControllers, используйте метод:

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)

Примечание: чтобы использовать второй способ, которым вам нужен ваш UINavigationController, вы нажимаете UIViewControllers на, делегат, и он должен соответствовать протоколу UINavigationControllerDelegate:

   class MyNavigationController: UINavigationController, UINavigationControllerDelegate {

    override func viewDidLoad() {
        self.delegate = self
    }

    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {

     // do what ever you need before going to the next UIViewController or back
     //this method will be always called when you are pushing or popping the ViewController

    }
}
2
ответ дан Maxim 28 August 2018 в 03:11
поделиться

Ваш вопрос very wide. Предложить, что есть одно простое решение для каждого сценария, немного наивное. Итак, давайте рассмотрим некоторые из этих сценариев.


Самый распространенный сценарий, о котором я спрашивал о переполнении стека в своем опыте, - это простая передача информации с одного контроллера вида на следующий.

Если мы используем раскадровку, наш первый контроллер представления может переопределить prepareForSegue, что и есть то, для чего оно предназначено. Объект UIStoryboardSegue передается при вызове этого метода и содержит ссылку на наш контроллер представления назначения. Здесь мы можем установить значения, которые мы хотим передать.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "MySegueID" {
        if let destination = segue.destinationViewController as? SecondController {
            destination.myInformation = self.myInformation
        }
    }
}

В качестве альтернативы, если мы не используем раскадровки, мы загружаем наш контроллер представлений из наконечника. Наш код немного проще.

func showNextController() {
    let destination = SecondController(nibName: "SecondController", bundle: NSBundle.mainBundle())
    destination.myInformation = self.myInformation
    self.showViewController(destination, sender: self)
}

В обоих случаях myInformation является свойством на каждом контроллере представления, в котором все данные должны передаваться с одного контроллера представления на следующий. Очевидно, что они не должны иметь одно и то же имя на каждом контроллере.


Мы также можем поделиться информацией между вкладками в UITabBarController.

В этом случае , это на самом деле потенциально даже проще.

Сначала создадим подкласс UITabBarController и дадим ему свойства для любой информации, которую мы хотим разделить между различными вкладками:

class MyCustomTabController: UITabBarController {
    var myInformation: [String: AnyObject]?
}

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

Теперь все наши контроллеры представлений в контроллер панели вкладок может получить доступ к этому свойству как таковому:

if let tbc = self.tabBarController as? MyCustomTabController {
    // do something with tbc.myInformation
}

И таким же образом путем подкласса UINavigationController мы можем использовать тот же подход для совместного использования данных по всему стеку навигации:

if let nc = self.navigationController as? MyCustomNavController {
    // do something with nc.myInformation
}

Существует несколько других сценариев. Ни в коем случае этот ответ не охватывает всех из них.

79
ответ дан nhgrif 28 August 2018 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: