Могу ли я вызвать метод DZNEmptyDataSet description () из любого места? - PullRequest
0 голосов
/ 19 сентября 2019

У меня установлен модуль DZNEmptyDataSet и кнопка «languages», которая вызывает всплывающий контроллер с представлением выбора, наблюдаемым в NotificationCenter в контроллере представления, называемом домашней работой.

Изменение представления средства выбора позволяетпользователь выбирает язык, это означает, что кнопка на том же контроллере представления, что и кнопка языков, теперь позволяет пользователю отображать все введенные слова (из другого контроллера представления, называемого словами).Задаваемое домашнее задание теперь основано только на одном языке (выбор представления пользователя), а не на всех языках со словами или несколькими словами из нескольких языков.Вторая кнопка называется «Выбран», поскольку набор домашних заданий становится только словами на языке, выбранном из представления выбора.

Проблема возникает, когда, например, в качестве набора домашних заданий использовались все французские слова и домашнее заданиеЗатем набор полностью очищается, а затем выбирается немецкий язык в окне выбора, но строка метода описания DZNEmptyDataSet по-прежнему ссылается на предыдущий выбор языка пользователя (информируя их о нажатии на французскую кнопку).Метод description вызывается только тогда, когда контроллер домашней работы впервые загружается в ОЗУ или когда контроллер домашней работы появляется после возврата к нему из контроллера слов.Кстати, именно так я получаю строку метода описания (как я говорил о 2 предложениях назад), чтобы изменить его поведение.Решение, которое мне нужно, состоит в том, чтобы вызывать метод description каждый раз, когда изменяется значение представления средства выбора.

Я думал о вызове description () из метода addObserver NotificationCenter, который в свою очередь находится в методе домашней работы viewDidLoadКонтроллер выглядит следующим образом:

        self.description(forEmptyDataSet: UIScrollView!)

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

Однако я получаю следующую ошибку:

        Using '!' is not allowed here; perhaps '?' was intended?

С предложением исправить замену '!'с '?'

также ошибка:

        Result of call to 'description(forEmptyDataSet:)' is unused

Я даже не знаю, что использовать для параметра метода UIScrollView для описания (который все еще подсвечен серым, как и ожидал меня)указать имя параметра UIScrollView).Кажется, что он передает тип UIScrollView, но кроме значения серого заполнителя, созданного из автозаполнения xCode, я не вижу никакого конкретного имени параметра.Я нажал опцию и нажал на метод описания и получил следующее:

        scrollView  A scrollView subclass informing the data source.

Или есть другой способ справиться с этим?

import UIKit
import SwiftUI
import DZNEmptyDataSet

class HomeworkViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarControllerDelegate, DZNEmptyDataSetDelegate, DZNEmptyDataSetSource {

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var clear: UIButton!
    @IBOutlet weak var all: UIButton!
    @IBOutlet weak var chosen: UIButton!
    @IBOutlet weak var languagePicker: UIButton!


    var words = [String]()
    var tableViewWords = [String]()
    var languages = [String]()
    var chosenLanguage = String()
    var chosenLanguageRemoved = false
    var chosenLanguageForHomework = Bool()
    var languagesWithWords = [String]()
    var languagesWithHomework = [String]()
    let wordString = "Words"
    var useHomework: Bool!

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(forName: .saveLanguage, object: nil, queue: OperationQueue.main) { (notification) in
            let languagePopupVC = notification.object as! LanguagePopupViewController
            self.chosenLanguage = languagePopupVC.language
            self.chosen.setTitle("    \(self.chosenLanguage.capitalized)", for: .normal)
            self.determineLanguagesWithWords()
            self.chosenEnableDisable()
            self.attributesChosenLanguage()
            self.description(forEmptyDataSet: UIScrollView!)
        }

        loadLanguages()
        print("languages in viewDidLoad in HomeworkViewController are: \(languages)")
        chosenLanguageLoad()
        print("chosenLanguage in viewDidLoad in homeworkViewcontroller is: \(chosenLanguage)")
        attributesChosenLanguage()

        enableUseHomework()
        loadHomeworkWords()

        clear.backgroundColor = .init(white: 0.95, alpha: 1.0)
        clear.layer.cornerRadius = 5
        clear.layer.borderWidth = 3
        clear.layer.borderColor = UIColor.clear.cgColor

        all.backgroundColor = .init(white: 0.95, alpha: 1.0)
        all.layer.cornerRadius = 5
        all.layer.borderWidth = 3
        all.layer.borderColor = UIColor.clear.cgColor

        chosen.backgroundColor = .init(white: 0.95, alpha: 1.0)
        chosen.layer.cornerRadius = 5
        chosen.layer.borderWidth = 3
        chosen.layer.borderColor = UIColor.clear.cgColor
        chosen.setTitle("    \(chosenLanguage.capitalized)", for: .normal)

        allEnableDisable()
        clearEnableDisable()
        determineLanguagesWithWords()
        chosenEnableDisable()

        languagePicker.backgroundColor = .init(white: 0.95, alpha: 1.0)
        languagePicker.layer.cornerRadius = 5
        languagePicker.layer.borderWidth = 3
        languagePicker.layer.borderColor = UIColor.clear.cgColor
        tableView.allowsMultipleSelection = false
        tableView.emptyDataSetSource = self
        tableView.emptyDataSetDelegate = self
        tableView.tableFooterView = UIView()
        tableView.reloadData()
        // Do any additional setup after loading the view.
    }

    func determineLanguagesWithWords() {
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if let savedWords = defaults.object(forKey: "words") as? [String] {
                languagesWithWords.removeAll()
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if languagesWithWords.contains(split[8]) == false {
                        languagesWithWords.append(split[8])
                    }
                }
            }
        }
    }

    func attributesChosenLanguage() {
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if let savedWords = defaults.object(forKey: "words") as? [String] {
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if split[8] == chosenLanguage {
                        if split[6] == "1" {
                            chosenLanguageForHomework = true
                        } else {
                            chosenLanguageForHomework = false
                            break
                        }
                    }
                }
            }
        }
    }

    func title(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
        let str = "There is no homework added."
        let attrs = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: UIFont.TextStyle.headline)]
        return NSAttributedString(string: str, attributes: attrs)
    }

    // Add description/subtitle on empty dataset
    func description(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
        var str = String()
        if all.isEnabled == true && chosen.isEnabled == true {
            str = "Tap 'All' or '\(chosenLanguage.capitalized)' button above, or swipe left in the words screen to add homework."
        } else if all.isEnabled == false && chosen.isEnabled == true {
            str = "Tap '\(chosenLanguage.capitalized)' button above, or swipe left on a word in 'Words' to add homework."
        } else if all.isEnabled == false && chosen.isEnabled == false {
            str = "Tap 'Languages' and choose a language that has words!"
        }
        let attrs = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)]
        return NSAttributedString(string: str, attributes: attrs)
    }

    // Add your image
    func image(forEmptyDataSet _: UIScrollView!) -> UIImage! {
        return UIImage(named: "empty_data_set")
    }

    func allEnableDisable() {
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if let savedWords = defaults.object(forKey: "words") as? [String] {
                print("savedWords in allEnableDisable in HomeworkViewController are: \(savedWords)")
                var homeworkSetCount = 0
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    print("split[6] in allEnableDisable in HomeworkViewController is: \(split[6])")
                    if split[6] == "1" {
                        homeworkSetCount += 1
                    }
                }
                print("homeworkSetCount in allEnableDisable in HomeworkViewController is: \(homeworkSetCount)")
                print("savedWords.count in allEnableDisable in HomeworkViewController is: \(savedWords.count)")
                if homeworkSetCount == savedWords.count || languagesWithWords.count == 1 {
                    all.isEnabled = false
                    all.alpha = 0.25
                    print("all button is disabled")
                } else {
                    all.isEnabled = true
                    all.alpha = 1.0
                    print("all button is enabled")
                }
            }
        }
    }

    func clearEnableDisable() {
        if tableViewWords.isEmpty {
            clear.isEnabled = false
            clear.alpha = 0.25
            print("clear button is disabled")
        } else {
            clear.isEnabled = true
            clear.alpha = 1.0
            print("clear button is enabled")
        }
    }

    func chosenEnableDisable() {
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if let savedWords = defaults.object(forKey: "words") as? [String] {
                var chosenLanguageSetCount = 0
                var chosenLanguageNotSetCount = 0
                var allLanguagesSetCount = 0
                var chosenLanguageWordCount = 0
                var allLanguagesWordCount = 0
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if split[8] == chosenLanguage {
                        chosenLanguageWordCount += 1
                        if split[6] == "0" {
                            chosenLanguageNotSetCount += 1
                        } else {
                            chosenLanguageSetCount += 1
                        }
                    } else {
                        allLanguagesWordCount += 1
                        if split[6] == "1" {
                            allLanguagesSetCount += 1
                        }
                    }
                }
                print("chosenLanguageSetCount + allLanguagesSetCount == chosenLanguageWordCount + allLanguagesWordCount) in chosenEnableDisable in HomeworkViewController is: \(chosenLanguageSetCount + allLanguagesSetCount == chosenLanguageWordCount + allLanguagesWordCount)")
                print("chosenLanguageNotSetCount in chosenEnableDisable in HomeworkViewController is: \(chosenLanguageNotSetCount)")
                print("languagesWithWords.contains(chosenLanguage) in chosenEnableDisable in HomeworkViewController is: \(languagesWithWords.contains(chosenLanguage))")
                print("languagesWithWords in chosenEnableDisable in HomeworkViewController are: \(languagesWithWords)")
                print("tableViewWords.count == words.count in chosenEnableDisable in HomeworkViewController is: \(tableViewWords.count == words.count)")
                print("tableViewWords.isEmpty in chosenEnableDisable in HomeworkViewController is: \(tableViewWords.isEmpty)")
                if ((chosenLanguageSetCount + allLanguagesSetCount == chosenLanguageWordCount + allLanguagesWordCount) || chosenLanguageNotSetCount > 0) && (languagesWithWords.contains(chosenLanguage) == true || tableViewWords.count != words.count || tableViewWords.isEmpty == true) {
                    chosen.isEnabled = true
                    chosen.alpha = 1.0
                    print("chosen button is enabled")
                } else {
                    chosen.isEnabled = false
                    chosen.alpha = 0.25
                    print("chosen button is disabled")
                }
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "languagePopup" {
            if let popupVC = segue.destination as? LanguagePopupViewController {
                popupVC.languages = self.languages
            }
        }
    }

    @IBAction func chosen(_ sender: UIButton) {
        // add user actions, "Cancel" to abort
        let ac = UIAlertController(title: "Use \(chosenLanguage.capitalized) Words", message: "Set homework as only all \(chosenLanguage.capitalized) words? Deletes any non \(chosenLanguage.capitalized) homework words!", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "Set", style: .default, handler: chosenLanguage))
        ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        present(ac, animated: true)
        print("chosen button tapped")
    }

    func chosenLanguage(action: UIAlertAction!) {
        tableViewWords.removeAll()
        words.removeAll()
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            print("defaults in chosenLanguage in HomeworkViewController are: \(defaults)")
            if var savedWords = defaults.object(forKey: "words") as? [String] {
                print("savedWords in chosenLanguage in HomeworkViewController are: \(savedWords)")
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if split[8] == chosenLanguage {
                        if split[6] == "0" {
                            let firstWord = split[0]
                            let secondWord = split[1]
                            let practiceWrongNoCorrectAnswer = split[2]
                            let homeworkWrongNoCorrectAnswer = split[3]
                            let attemptCount = split[4]
                            let homeworkAttemptCount = split[5]
                            let homeworkSet = "1"
                            let useHomework = split[7]
                            let languageAdded = split[8]
                        words.append("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(languageAdded)")
                        tableViewWords.append("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(languageAdded)")
                        } else {
                            words.append(savedWord)
                            tableViewWords.append(savedWord)
                        }
                    } else {
                        if split[6] == "1" {
                            let firstWord = split[0]
                            let secondWord = split[1]
                            let practiceWrongNoCorrectAnswer = split[2]
                            let homeworkWrongNoCorrectAnswer = split[3]
                            let attemptCount = split[4]
                            let homeworkAttemptCount = split[5]
                            let homeworkSet = "0"
                            let useHomework = split[7]
                            let languageAdded = split[8]
                        words.append("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(languageAdded)")
                        } else {
                            words.append(savedWord)
                        }
                    }
                }
                savedWords.removeAll()
                print("savedWords after clear all in chosenLanguage method in HomeworkViewController are: \(savedWords)")
            }
            saveWords()
            chosenLanguageForHomework = true
            print("chosenLanguageForHomework in chosenLanguage method in HomeworkViewController is: \(chosenLanguageForHomework)")
            print("words in chosenLanguage method in HomeworkViewController are: \(words)")
        }
        loadHomeworkWords()
        tableView.reloadData()
        clearEnableDisable()
        allEnableDisable()
        chosenEnableDisable()
    }

    @IBAction func all(_ sender: UIButton) {
        let ac = UIAlertController(title: "Set All as Homework", message: "Use words from all \(languages.count) languages as homework?", preferredStyle: .alert)
        // add user actions, "Cancel" to abort
        ac.addAction(UIAlertAction(title: "OK", style: .default, handler: allLanguages))
        ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        present(ac, animated: true)
        print("All button tapped")
    }

    func allLanguages(action: UIAlertAction) {
        words.removeAll()
        tableViewWords.removeAll()
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if var savedWords = defaults.object(forKey: "words") as? [String] {
                print("savedWords in allWords in HomeworkViewController are: \(savedWords)")
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if split[6] == "0" {
                        let firstWord = split[0]
                        let secondWord = split[1]
                        let practiceWrongNoCorrectAnswer = split[2]
                        let homeworkWrongNoCorrectAnswer = split[3]
                        let attemptCount = split[4]
                        let homeworkAttemptCount = split[5]
                        let homeworkSet = "1"
                        let useHomework = split[7]
                        let language = split[8]
                    words.append("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(language)")
                    tableViewWords.append("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(language)")
                    } else {
                        words.append(savedWord)
                        tableViewWords.append(savedWord)
                    }
                }

                savedWords.removeAll()
                print("words in allWords in HomeworkViewController are: \(words)")
                print("savedWords after clearAll in allWords in HomeworkViewController are: \(savedWords)")
            }
        }
        chosenLanguageForHomework = false
        print("chosenLanguageForHomework in chosenLanguage method in HomeworkViewController is: \(chosenLanguageForHomework)")
        saveWords()
        loadHomeworkWords()
        clearEnableDisable()
        allEnableDisable()
        chosenEnableDisable()
        tableView.reloadData()
    }

    func determineLanguagesWithHomework() {
        if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {
            if let savedWords = defaults.object(forKey: "words") as? [String] {
                languagesWithHomework.removeAll()
                for savedWord in savedWords {
                    let split = savedWord.components(separatedBy: "::")
                    if split[6] == "1" {
                        if languagesWithHomework.contains(split[8]) == false {
                            languagesWithHomework.append(split[8])
                        }
                    }
                }
            }
        }
    }

    override func shouldPerformSegue(withIdentifier Homework: String, sender: Any?) -> Bool {
        return true
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableViewWords.count
    }

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let delete = UIContextualAction(style: .destructive, title: "Delete") {
            (action, sourceView, completionHandler) in

            let deleteHomeworkWord = self.tableViewWords[indexPath.row]
            let split = deleteHomeworkWord.components(separatedBy: "::")
            let firstWord = split[0]
            let secondWord = split[1]
            let practiceWrongNoCorrectAnswer = split[2]
            let homeworkWrongNoCorrectAnswer = split[3]
            let attemptCount = split[4]
            let homeworkAttemptCount = split[5]
            let homeworkSet = "0"
            let useHomework = split[7]
            let language = split[8]

            var unsetHomeworkIndex = 0
            for word in self.words {
                if word == deleteHomeworkWord {
                    print("words before remove: \(self.words)")
                    self.words.remove(at: unsetHomeworkIndex)
                self.words.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(practiceWrongNoCorrectAnswer)"+"::"+"\(homeworkWrongNoCorrectAnswer)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(useHomework)"+"::"+"\(language)", at: unsetHomeworkIndex)
                    print("words after insert: \(self.words)")
                    break
                }
                unsetHomeworkIndex += 1
            }
            print("words in delete contextualAction in HomeworkViewController are: \(self.words)")

            // delete item at indexPath
            self.tableViewWords.remove(at: indexPath.row)
            tableView.beginUpdates()
            tableView.deleteRows(at: [indexPath], with: .fade)
            tableView.endUpdates()
            self.saveWords()
            self.allEnableDisable()
            self.clearEnableDisable()
            self.chosenEnableDisable()

            completionHandler(true)
        }

        delete.backgroundColor = UIColor.red

        if let cell = tableView.cellForRow(at: indexPath) {
            cell.isHighlighted = true
        }
        let swipeConfiguration = UISwipeActionsConfiguration(actions: [delete])

        return swipeConfiguration
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "homework", for: indexPath)

        let tableViewWord = tableViewWords[indexPath.row]

        if tableViewWord != "" {
            if tableViewWord != "::" {
                let split = tableViewWord.components(separatedBy: "::")
                if split[6] == "1" {
                    print("split 0 in tableVew(cellForRowAt:) in HomeworkViewController is: \(split[0])")

                    cell.textLabel?.text = split[0] + "      " + "(\(split[8].capitalized))"

                    cell.detailTextLabel?.text = ""
                }
            } else {
                cell.textLabel?.text = ""
                cell.detailTextLabel?.text = ""
            }
        }
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        if let cell = tableView.cellForRow(at: indexPath) {
            if cell.detailTextLabel?.text == "" {
                let tableViewWord = tableViewWords[indexPath.row]
                if tableViewWord.isEmpty == false {
                    let split = tableViewWord.components(separatedBy: "::")
                    cell.detailTextLabel?.text = split[1]
                }
            } else {
                cell.detailTextLabel?.text = ""
            }
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        loadLanguages()
        chosenLanguageLoad()
        attributesChosenLanguage()
        enableUseHomework()
        loadHomeworkWords()
        print("chosenLanguage in viewWillAppear in HomeworkViewcontroller is: \(chosenLanguage)")
        chosen.setTitle("    \(chosenLanguage.capitalized)", for: .normal)
        tableView.reloadData()
        determineLanguagesWithWords()
        allEnableDisable()
        clearEnableDisable()
        chosenEnableDisable()
    }
}
import UIKit

class LanguagePopupViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    var languages = [String]()
    var language = String()
    @IBOutlet weak var languagePicker: UIPickerView!
    @IBOutlet weak var saveLanguage: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        print("languages in viewDidLoad in LanguageopupViewController are: \(languages)")
        languagePicker.dataSource = self
        languagePicker.delegate = self
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        languages.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return languages[row].capitalized
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        language = languages[row]
        print("language in pickerViewDidSelectRow in LanguagePopupViewController is: \(language)")
    }

    @IBAction func saveLanguage(_ sender: UIButton) {
        NotificationCenter.default.post(name: .saveLanguage, object: self)
        dismiss(animated: true)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...