У меня есть class со ссылкой на другой class. У студенческого класса есть переменная со ссылкой на информацию о модуле. Я хочу вставить moduleId в массив, но структура состоит из разных типов объектов и имеет тип moduleRef. Я хотел бы получить moduleId типа string. Как я могу получить этот элемент moduleId из формы ModuleRef.
class Student {
var firstName: String
var lastName: String
var modulesRefs: [ModuleRef]
var fullName: String {
return self.firstName + " " + self.lastName
}
init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
self.firstName = firstName
self.lastName = lastName
self.modulesRefs = modulesRefs
}
func addModuleId(_ moduleId: String) {
self.modulesRefs.insert(moduleId, at: 0)
}
func removeModuleId(_ moduleId: String) {
self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
}
}
class ModuleRef {
var moduleName: String
var moduleId: String
var moduleStartdate: Int
init(moduleName: String, moduleId: String, moduleStartdate: Int) {
self.moduleName = moduleName
self.moduleId = moduleId
self.moduleStartdate = moduleStartdate
}
}
Cannot convert value of type 'String' to expected argument type 'ModuleRef'
@SohilR.Memon insert находится в Swift's standard library
Вы звоните addModuleId, чтобы вставить новое значение?
@SohilR.Memon да. Что такое строка
как насчет moduleName и moduleStartdate, когда вы передаете только moduleId, каково будет значение этих двух переменных?
@SohilR.Memon Я не использую ни один из них на данный момент
хорошо, тогда это может быть nil? Поскольку в названии class "ModuleRef" вы сделали их обязательными.
@SohilR.Memon Я, наверное, могу это изменить
Да, вы можете сделать это nil или вы можете просто передать значение по умолчанию, например пустую строку и значение 0, что вы скажете?
Проверьте ответ!





Вам нужно сделать массив типа Any..
var modulesRefs: [Any] = []
Вы можете добавить элемент в массив следующим образом...
modulesRefs.append("Test string")
let obj = ModuleRef(...)
modulesRefs.append(obj)
И когда вы получаете доступ к элементу, вам нужно использовать либо if let, либо guard let, чтобы безопасно проверить его тип.
Например.
for obj in modulesRefs {
if let strType = obj as? String {
print("\(obj) is string type")
} else if let moduleRefObj = obj as? ModuleRef {
print("\(obj) is ModuleRef type")
}
Any. Всего для двух разных типов используется общий протокол.
Вам необходимо обновить тип массива до Any следующим образом:
var modulesRefs: [Any]
При доступе к значению из массива,
if let moduleRef = modulesRefs[index] as? ModuleRef {
} else if let str = modulesRefs[index] as? String {
}
Any. Всего для двух разных типов используется общий протокол.
@vadian это также смутило меня, зачем мне пытаться получить moduleId из другого класса
В своем коде вы сделали значения class ModuleRef { ... } обязательными, и вы просто передаете одно значение moduleId и добавляете его к Array из ModuleRef, что является совершенно неправильным подходом. Итак, на основании того, что вы сказали, это обновленный код вашего кода:
class Student {
var firstName: String
var lastName: String
var modulesRefs: [ModuleRef]
var fullName: String {
return self.firstName + " " + self.lastName
}
init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
self.firstName = firstName
self.lastName = lastName
self.modulesRefs = modulesRefs
}
func addModuleId(_ moduleId: String) {
// This will be your updated intializer where you can pass any value you want and other will be taken as default value
let moduleRef = ModuleRef(moduleId: moduleId)
self.modulesRefs.insert(moduleRef, at: 0)
}
func removeModuleId(_ moduleId: String) {
self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
}
}
class ModuleRef {
var moduleName: String
var moduleId: String
var moduleStartdate: Int
/// Here you can provide all the default values which you don't want to pass
init(moduleName: String = "", moduleId: String = "", moduleStartdate: Int = 0) {
self.moduleName = moduleName
self.moduleId = moduleId
self.moduleStartdate = moduleStartdate
}
}
Кроме того, вы также можете передать значение nil для всех, создавая переменную как optional. Дайте мне знать, если у вас есть путаница!
Вы не можете вставить ModuleRef, просто передав String.
Вам нужно создать экземпляр, например, добавив полное имя учащегося и временную метку UNIX текущей даты.
func addModuleId(_ moduleId: String) {
let moduleRef = ModuleRef(moduleName: self.fullName,
moduleId: moduleId,
moduleStartDate: Int(Date().timeIntervalSince1970))
self.modulesRefs.insert(moduleRef, at: 0)
}
И для удаления объекта это более эффективно, однако класс должен соответствовать Equatable
func removeModuleId(_ moduleId: String) {
guard let index = self.modulesRefs.firstIndex(where: {$0.moduleId == moduleId}) else { return }
self.modulesRefs.remove(at: index)
}
Я бы даже объявил moduleStartDate как Date.
это здорово, но что, если я просто хочу, чтобы moduleId был в объекте moduleRef. Как я могу это сделать. Я не могу просто исключить их. Выдаст мне ошибку с сообщением invalid number of arguments?
Что именно вы собираетесь выполнить с помощью метода addModuleId? Учтите, что массив modulesRefs содержит несколько объектов ModuleRef, которые имеют 3 свойства соответственно.
не беспокойтесь, я установил значения по умолчанию для остальных. благодаря.
Вы можете вставить значения Type ModuleRef в этот массив. Поэтому я могу изменить функции как:
func addModuleId(_ moduleId: String) {
let module = ModuleRef(moduleName: "", moduleId: moduleId, moduleStartdate: 0)
self.modulesRefs.insert(module, at: 0)
}
func removeModuleId(_ moduleId: String) {
modulesRefs.removeAll(where: { $0.moduleId == moduleId })
}
NB: Если вам не нужны moduleName и moduleStartdate все время, вы можете пометить их как необязательные.
То, что вы пытаетесь сделать, на самом деле означает, что в вашем дизайне есть изъян.
Если вам нужна функциональность для вызова student.addModuleId(moduleId), это означает, что Student не должен содержать массив ModuleRef. (Или, по крайней мере, иметь механизм для извлечения всего ModuleRef по его идентификатору, а затем вставлять этот ModuleRef внутрь массива)
При этом после выяснения вашего дизайна, для которого он будет: modules: [ModuleRef] или moduleIds: [String], есть еще кое-что, что вы можете использовать:
Протокол Equatable. Если вы сделаете ModuleRef соответствующим протоколу Equatable и проверите его равенство с id, то Swift предоставит вам доступ к методу remove(element:_), и метод removeModuleId() вам больше не понадобится.
Или, если все ModuleId уникальны, вы также можете реализовать протокол Hashable и использовать Set<ModuleRef> вместо массива, чтобы иметь методы удаления и вставки O (1). (прямо сейчас удалите функцию, занимает O(n) времени)
Можете ли вы показать метод вставки?