Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以打印数据,但可以';t在Swift中将其分配给标签_Swift_String_Viewdidload_Computed Properties - Fatal编程技术网

我可以打印数据,但可以';t在Swift中将其分配给标签

我可以打印数据,但可以';t在Swift中将其分配给标签,swift,string,viewdidload,computed-properties,Swift,String,Viewdidload,Computed Properties,我将API调用中的数据发送到InfoController viewDidLoad。在那里,我能够安全地将它存储在skillName常量中,并打印它,通过控制台接收所有信息 当我尝试将此变量分配给skillLabel时,问题就出现了 override func viewDidLoad() { super.viewDidLoad() configureViewComponents() fetchPokemons { (names) in guard var s

我将API调用中的数据发送到InfoController viewDidLoad。在那里,我能够安全地将它存储在skillName常量中,并打印它,通过控制台接收所有信息

当我尝试将此变量分配给skillLabel时,问题就出现了

override func viewDidLoad() {
    super.viewDidLoad()
    configureViewComponents()
    fetchPokemons { (names) in
        guard var skillName = names as? String else { return }
        self.pokemon?.skillName = skillName
        
        self.allNames = skillName
        print(self.allNames)
    }
}
在那里,当我打印所有名称时,控制台显示我需要的所有数据。以下是数据的外观:

我想使用这些数据的计算属性是:

var pokemon: Pokemon? {
    didSet {
        guard let id        = pokemon?.id else { return }
        guard let data      = pokemon?.image else { return }

        
        navigationItem.title = pokemon?.name?.capitalized
        infoLabel.text = pokemon?.description
        infoView.pokemon = pokemon
        
        if id == pokemon?.id {
            imageView.image = UIImage(data: data)
            infoView.configureLabel(label: infoView.skillLabel, title: "Skills", details: "\(allNames)")
        }
    }
}
PD:allNames是我在InfoController类级别拥有的字符串变量

这是我的应用在运行时的外观:

我的目标是让details参数显示skillName数据,但它返回nil,idk why。有什么建议吗

EDIT1:从我的服务类获取口袋妖怪数据的我的函数是:

func fetchPokemons(handler: @escaping (String) -> Void) {
    controller.service.fetchPokes { (poke) in
        DispatchQueue.main.async {
            self.pokemon? = poke
            
            guard let skills = poke.abilities else { return }
            
            for skill in skills {
                
                guard let ability = skill.ability else { return }
                
                guard var names = ability.name!.capitalized as? String else { return }
                
                self.pokemon?.skillName = names
                handler(names)
            }
        }
    }
}
EDIT2:InfoView类看起来像:

class InfoView: UIView {

// MARK: - Properties
var delegate: InfoViewDelegate?

//  This whole block assigns the attributes that will be shown at the InfoView pop-up
//  It makes the positioning of every element possible
var pokemon: Pokemon? {
    didSet {
        guard let pokemon   = self.pokemon else { return }
        guard let type      = pokemon.type else { return }
        guard let defense   = pokemon.defense else { return }
        guard let attack    = pokemon.attack else { return }
        guard let id        = pokemon.id else { return }
        guard let height    = pokemon.height else { return }
        guard let weight    = pokemon.weight else { return }
        guard let data      = pokemon.image else { return }
        
        if id == pokemon.id {
            imageView.image = UIImage(data: data)
        }
        nameLabel.text = pokemon.name?.capitalized
        
        configureLabel(label: typeLabel, title: "Type", details: type)
        configureLabel(label: pokedexIdLabel, title: "Pokedex Id", details: "\(id)")
        configureLabel(label: heightLabel, title: "Height", details: "\(height)")
        configureLabel(label: defenseLabel, title: "Defense", details: "\(defense)")
        configureLabel(label: weightLabel, title: "Weight", details: "\(weight)")
        configureLabel(label: attackLabel, title: "Base Attack", details: "\(attack)")
    }
}

let skillLabel: UILabel = {
    let label = UILabel()
    return label
}()

let imageView: UIImageView = {
    let iv = UIImageView()
    iv.contentMode = .scaleAspectFill
    return iv
}()
. . .
}
infoView.configureLabel是这样的:

func configureLabel(label: UILabel, title: String, details: String) {
    let attributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: "\(title):  ", attributes: [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: Colors.softRed!]))
    attributedText.append(NSAttributedString(string: "\(details)", attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.gray]))
    label.attributedText = attributedText
}
编辑3:结构设计

struct Pokemon: Codable {
    var results: [Species]?
    var abilities: [Ability]?
    var id, attack, defense: Int?
    var name, type: String?
...
}

struct Ability: Codable {
    let ability: Species?
}

struct Species: Codable {
    let name: String?
    let url: String?
}
跳转到Edit2段落获得最终答案

初步答复: 在控制器获取所有数据后,您的UI似乎没有得到更新

由于所有UI配置代码都在
var pokemon/didSet
中,因此最好将其提取到单独的方法中

private func updateView(带pokemon:pokemon?,详细信息:String?){
guard let id=pokemon?.id,let data=pokemon?.image else{return}
navigationItem.title=pokemon?.name?.capitalized
infoLabel.text=pokemon?.description
infoView.pokemon=pokemon
如果id==口袋妖怪?.id{
imageView.image=UIImage(数据:数据)
infoView.configureLabel(标签:infoView.skillLabel,标题:“技能”,详细信息:详细信息??)
}
}
现在您可以轻松地调用
didSet

var口袋妖怪:口袋妖怪?{
didSet{updateView(with:pokemon,details:allNames)}
}
还有
fetchPokemons
completion

override func viewDidLoad(){
super.viewDidLoad()
configureViewComponents()
获取口袋妖怪{(名称)在
guard var skillName=名称为?字符串else{return}
self.pokemon?.skillName=skillName
self.allNames=skillName
打印(self.allNames)
DispatchQueue.main.async{
self.updateView(使用:self.pokemon,详细信息:self.allNames)
}
}
}
在主队列上进行任何UI设置都非常重要

编辑: fetch函数可能是导致问题的原因!您多次调用处理程序:

func-fetchPokemons(处理程序:@escaping(String)->Void){
controller.service.fetchPokes{(戳)入
DispatchQueue.main.async{
self.pokemon?=戳
守卫技能=poke.abilities else{return}
让names=skills.compactMap{$0.ability?.name?.capitalized}.joined(分隔符:“,”)
处理程序(名称)
}
}
}
编辑2: 查看代码库后,您需要更改以下几项:

1. <代码>抓取口袋妖怪实现 每个口袋妖怪都会调用
controller.service.fetchPokes
的处理程序,因此我们需要检查获取的处理程序是否为当前处理程序(self.pokemon),然后使用正确格式的技能调用
处理程序

func-fetchPokemons(处理程序:@escaping(String)->Void){
controller.service.fetchPokes{(戳)入
guard poke.id==self.pokemon?.id else{return}
self.pokemon?=戳
让names=poke.abilities?.compactMap{$0.ability?.name?.capitalized}.joined(分隔符:“,”)
处理程序(名称为“-”)
}
}
2.更新
viewDidLoad()
现在只需将
名称
值传递给标签即可

override func viewDidLoad(){
super.viewDidLoad()
configureViewComponents()
获取口袋妖怪{(名称)在
self.pokemon?.skillName=名称
self.infoView.configureLabel(标签:self.infoView.skillLabel,标题:“技能”,详细信息:名称)
}
}
3.重构
var pokemon:pokemon?
didSet-observer
var口袋妖怪:口袋妖怪?{
迪塞特{
guard let pokemon=pokemon,let data=pokemon.image else{return}
navigationItem.title=pokemon.name?.capitalized
infoLabel.text=pokemon.description!
infoView.pokemon=pokemon
imageView.image=UIImage(数据:数据)
}
}

如果你通过了
self.pokemon?.skillName
而不是
self.allNames
?同样的结果,而且我的CollectionView加载速度比重构前慢。你能在问题中包含更多的代码吗?更多的背景会更好。需要检查的一件事是
infoView.skillLabel
是否与当前显示的相同。如果您提到collectionView,可能会尝试在抓取完成后调用
reloadData()
?好吧,我的应用程序是这样工作的:CollectionViewController显示每个项目的图像和名称。如果你点击一个项目,它会推送到我的InfoViewController,在那里我真的想展示技能。我认为
infoView.skillLabel
与当前显示的绝对相同,否则它不会显示空的“”,而不是我想要的值,因此
infoView.skillLabel
本身不在某种UICollectionViewCell中,而是一个静态标签,对吗?我很想看到
infoView.configureLabel的实现,也许还有
infoView