Static constructors generally do lead to the problems you have encountered, where the implementation tends to be procedural, and complexity increases as the constructed classes become more intricate.

This can be made more manageable by using a builder pattern, which is implemented as a class that exists for the purpose of constructing the final class. This allows you to maintain an object-oriented approach. 

The builder class can be used in the static `parse` function, so the interface can stay the same if needed. 

Ideally, the `parse` function should be implemented as a convenience initialiser since it is constructing an object instance.

To answer your questions:

> Should local variables such as `allInput` that are passed in to more than one function be instance variables?

Yes. These should be instance variables of the builder. See the example below.
 
> Should functions like 'determineMeetingFormat' and 'parseParticipants' be called directly into the Meeting constructor or be assigned to local constants that clearly defines what's being returned?

Yes. Local constants/variables are self documenting to some degree and hence improve readability. They also give you an easy reference to trace during debugging if needed.

> Would it be better to make `location` and `description` optional Strings rather than empty strings?

Yes. By making these optionals the compiler can help you in those places where you might need to check if the string exists. The alternative is to use `isEmpty` which you can only see at runtime / unit tests. Compile time checking gives more immediate results.

> Is making all my functions and instance variables static the best way to make this behave like a static class?

Not always. Static methods behave like singletons in many ways, which has many disadvantages, such as being hard to test and debug. They are often provided as conveniences which delegate to an equivalent instance method. You are essentially creating a constructor, which would be better implemented as a convenience initializer (i.e. `init`).

**Example 1**:

The example below shows one way that the builder pattern could be implemented:

*Builder class*

    class MeetingParser {
        let input: String

        // Instance variables for the parsed values. 
        // These can be optionals for more safety.
        var parsedHostCodes: [HostCode]!
        var parsedPassCodes: [PassCode]!
        var parsedPhoneNumbers: [PhoneNumber]!
        var meetingFormat: MeetingFormat!
        var participants: [Participant]!
        var isAtt: Bool
        var host: String!

        init(input: String) {
            self.input = input
        }

        func parse() {
            // The functions below would access the instance variables.
            parsedHostCodes = parseHostCode()
            parsedPasscodes = parseParticipantCode()
            parsedPhoneNumbers = parsePhoneNumber()
            meetingFormat = determineMeetingFormat()
            participants = parseParticipants()
            isAtt = input.contains(pattern: attRegex)
            host = retrieveHost()
        }
    }

*Meeting convenience initialiser*

    extension Meeting {
        init(event: EKEvent) {
            let allInput = "\(event.title)\n\(event.location)\n\(event.description)"
            let parse = MeetingParse(input: allInput)
            parser.parse()
            self.UUID = event.eventIdentifier
            self.title = event.title
            self.description = event.description
            self.location = event.location
            self.host = parser.host
            self.startTime = event.startDate
            self.endTime = event.endDate
            self.allday = event.isAllDay
            self.passcodes = parser.parsedPasscodes
            self.hostcodes = parser.parsedHostCodes
            self.phoneNumbers = parser.parsedPhoneNumbers
            self.attendees = parser.participants
            self.isAtt = parser.isAtt
            self.meetingFormat = parser.meetingFormat
        }
    }


**Example 2**

Below is a second example, also using a builder class, although this one assumes the properties of the `Meeting` class are implicit optionals, which simplifies the construction to some extent. This comes at the cost of reducing safety as it potentially allows nils to be unwrapped which would result in a runtime crash.

    class MeetingParser {
        let event: EKEvent
        let meeting: Meeting

        init(event: EKEvent, meeting: Meeting) {
            self.event = event
            self.meeting = meeting
        }

        func build() {
            meeting.UUID = event.eventIdentifier
            meeting.title = event.title
            meeting.description = event.description
            meeting.location = event.location
            meeting.host = retrieveHost()
            meeting.startTime = event.startDate
            meeting.endTime = event.endDate
            meeting.allday = event.isAllDay

            // Class methods re-use the values in meeting.
            // Could instead use instance variables to hold intermediate values.
            meeting.parsedHostCodes = parseHostCode()
            meeting.parsedPasscodes = parseParticipantCode()
            meeting.parsedPhoneNumbers = parsePhoneNumber()
            meeting.meetingFormat = determineMeetingFormat()
            meeting.participants = parseParticipants()
            meeting.isAtt = input.contains(pattern: attRegex)
        }
    }

    extension Meeting {
        // Meeting properties are defined as simplicity unwrapped optionals:
        // var title: String! = nil
        init(event: EKEvent) {
            let builder = MeetingBuilder(event: event, meeting: self)
            builder.build()
        }
    }

**Example usage:**

    let meeting = Meeting(event: event)