Declan McKenna
Declan McKenna

Reputation: 4910

Macbook crashes when compiling app

When compiling my project the compiler gets stuck on this class, after about 5 minutes of attempting to build I get a message telling me I'm out of system memory and to close some apps to continue. Is there something in this code which could cause the compiler to crash?

I'm using XCode9, seeing as my entire computer is crashing could this be a fault with XCode?

import UIKit

class ConferenceNumberViewController: UITableViewController, UINavigationControllerDelegate {

    let sections = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    let countries = CallIn.Data.allCountries
    var indexedCountries =
    [
        "A": [String](),
        "B": [String](),
        "C": [String](),
        "D": [String](),
        "E": [String](),
        "F": [String](),
        "G": [String](),
        "H": [String](),
        "I": [String](),
        "J": [String](),
        "K": [String](),
        "L": [String](),
        "M": [String](),
        "N": [String](),
        "O": [String](),
        "P": [String](),
        "Q": [String](),
        "R": [String](),
        "S": [String](),
        "T": [String](),
        "U": [String](),
        "V": [String](),
        "W": [String](),
        "X": [String](),
        "Y": [String](),
        "Z": [String]()
    ]
    var countryNumberIndex: Int = 0
    var indexedConferenceNumbers = CallIn.Data.indexedConferenceNumbers
    var selectedConferenceNumber: CallIn.ConferenceNumber!

    override func viewDidLoad() {
        super.viewDidLoad()

        countryAndConference = true
        // Do any additional setup after loading the view.

        //hide back button according to design
        navigationItem.setHidesBackButton(true, animated: false)

        for section in sections {
            for country in countries {
                let searchCharacter: Character = section.characters.first!
                let countryCheck: Character = country.characters.first!
                let compare = countryCheck == searchCharacter
                if compare {
                    indexedCountries[section]!.append(country)
                }
            }
        }

//        indexedConferenceNumbers = indexedConferenceNumbers.sort(sortFunc) // moved the sorting to the Data class

    }

    /*func sortFunc(num1: CallIn.ConferenceNumber, num2: CallIn.ConferenceNumber) -> Bool {
        return num1.country == num2.country ? (num1.typeOfNumber > num2.typeOfNumber) : (num1.country < num2.country)
    }*/ // moved the sorting to the Data class

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

    // custom section view
    override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView //recast your view as a UITableViewHeaderFooterView
        header.contentView.backgroundColor = Design.Colours.lightBlue      // make the background light grey
        if (accessibilityON){
            header.textLabel!.font = UIFont(descriptor: UIFontDescriptor.regularDescriptor(UIFontTextStyle.body.rawValue), size: 0)
        } else { header.textLabel!.font = UIFont.systemFont(ofSize: 13)}
        //  header.textLabel!.textColor = Design.Colours.subtextDarkGrey    //make the text dark grey
        // header.textLabel!.font = UIFont.systemFontOfSize(13)            // set size of text
        //header.alpha = 0.5 //make the header transparent
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CountryCell", for: indexPath)
        let country = cell.viewWithTag(511) as! UILabel
        let number = cell.viewWithTag(512) as! UILabel
        let type = cell.viewWithTag(513) as! UILabel

        // we have to calculate the index (jump) because the conference numbers list is single array (there are no sections)
        var jump = 0
        for index in 0...(indexPath as NSIndexPath).section {
            (index == (indexPath as NSIndexPath).section) ? (jump = jump + (indexPath as NSIndexPath).row) : (jump = jump + indexedCountries[sections[index]]!.count)
        }

        country.text = indexedConferenceNumbers[jump].country
        number.text = indexedConferenceNumbers[jump].conferenceNumber
        type.text = indexedConferenceNumbers[jump].typeOfNumber
        return cell
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return indexedCountries[sections[section]]!.count
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if (countriesPerSection("\(sections[section])").count == 0) {
            return nil
        }
        return sections[section] as String
    }

    //index on the right side of the screen
    override func sectionIndexTitles(for tableView: UITableView) -> ([String]!){
        return self.sections
    }



    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if (countriesPerSection("\(sections[section])").count == 0) {
            return 0.1
        }
        return 30.0
    }


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let indexPath = self.tableView.indexPathForSelectedRow {
            tableView.deselectRow(at: indexPath, animated: true)
            let selectedCell = tableView.cellForRow(at: indexPath) as UITableViewCell!
            let country = selectedCell?.contentView.viewWithTag(511) as! UILabel
            let number = selectedCell?.contentView.viewWithTag(512) as! UILabel
            let type = selectedCell?.contentView.viewWithTag(513) as! UILabel
            // Set the number to be passed to SettingDetailsViewController after the unwind segue.
            selectedConferenceNumber = CallIn.ConferenceNumber(country: country.text!, conferenceNumber: number.text!, typeOfNumber: type.text!, isoCode: "")
        }
    }

    private func countriesPerSection(_ section: String) -> [String] {
        var matches = [String]()
        for country in indexedCountries["\(section)"]! {
            matches.append(country)
        }

        return matches
    }

    private func conferenceNumbersPerCountry(_ country: String) -> Array<CallIn.ConferenceNumber> {
        var matches = Array<CallIn.ConferenceNumber>()
        for numbers in indexedConferenceNumbers {
            if numbers.country == country {
                let conferenceNumber = CallIn.ConferenceNumber(country: numbers.country, conferenceNumber: numbers.conferenceNumber, typeOfNumber: numbers.typeOfNumber, isoCode: numbers.isoCode)
                matches.append(conferenceNumber)
            }
        }
        return matches
    }

    @IBAction private func goBack(_ sender: UIBarButtonItem) {
        self.navigationController!.popViewController(animated: true)
    }
}

Upvotes: 3

Views: 74

Answers (2)

rmaddy
rmaddy

Reputation: 318914

The Swift compiler is probably having issues with such a large dictionary and trying to infer the proper type for the indexedCountries variable.

One solution is to provide the type:

var indexedCountries: [String, [String]] =

A better solution is to avoid such code. Change the hardcoded dictionary to just the following:

var indexedCountries = [String, [String]]()

And then in viewDidLoad you can populate it:

for letter in sections {
    indexedCountries[letter] = [String]()
}

This avoid a lot of extra typing, avoids potential typos, and makes the compiler's job a lot simple (faster compiling).

You may also benefit from updating the declaration for sections to be:

let sections: [String] = [ "A", ... ]

Upvotes: 3

Declan McKenna
Declan McKenna

Reputation: 4910

Downgrading to XCode 8.3.3 fixed this for me. I'll edit this answer if I find a work around for getting 9.0 or 9.1 to work.

Upvotes: 0

Related Questions