71373


swift初学者です。  
チュートリアルを参考にSNSアプリを制作しています。  
xcodeのバージョンは12.0.1です。  
タイトルのエラーが解消でず質問させていただきます。  
'UserRelationship'の値を'String'に変換できないとはどういうことでしょうか？

[code]

    import UIKit
    
    protocol UserFollowTableViewCellDelegate: AnyObject {
        func didTapFollowUnfollowButton(model: String)
    }
    
    enum FollowState {
        case following, not_following
    }
    
    struct UserRelationship {
        let username: String
        let name: String
        let type: FollowState
    }
    
    class UserFollowTableViewCell: UITableViewCell {
        static let identifier = "UserFollowTableViewCell"
        
        weak var delegate: UserFollowTableViewCellDelegate?
        
        private var model: UserRelationship?
        
        private let profileImageView: UIImageView = {
            let imageView = UIImageView()
            imageView.layer.masksToBounds = true
            imageView.backgroundColor = .secondarySystemBackground
            imageView.contentMode = .scaleAspectFill
            return imageView
        }()
        
        private let nameLabel: UILabel = {
            let label = UILabel()
            label.numberOfLines = 1
            label.font = .systemFont(ofSize: 17, weight: .semibold)
            label.text = "太郎"
            return label
        }()
        
        private let usernameLabel: UILabel = {
            let label = UILabel()
            label.numberOfLines = 1
            label.font = .systemFont(ofSize: 16, weight: .regular)
            label.text = "@太郎"
            label.textColor = .secondaryLabel
            return label
        }()
        
        private let followButton: UIButton = {
            let button = UIButton()
            button.backgroundColor = .link
            return button
        }()
        
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            contentView.clipsToBounds = true
            contentView.addSubview(nameLabel)
            contentView.addSubview(usernameLabel)
            contentView.addSubview(profileImageView)
            contentView.addSubview(followButton)
            
            followButton.addTarget(self,
                                   action: #selector(didTapFollowButton),
                                   for: .touchUpInside)
        }
        
        @objc private func didTapFollowButton() {
            guard let model = model else {
                return
            }
            delegate?.didTapFollowUnfollowButton(model: model)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        public func configure(with model: UserRelationship) {
            self.model = model
            nameLabel.text = model.name
            usernameLabel.text = model.username
            switch model.type {
            case .following:
                // フォロー解除ボタン
                followButton.setTitle("フォロー解除", for: .normal)
                followButton.setTitleColor(.label, for: .normal)
                followButton.backgroundColor = .systemBackground
                followButton.layer.borderWidth = 1
                followButton.layer.borderColor = UIColor.label.cgColor
            case .not_following:
                //　フォローボタン
                followButton.setTitle("フォローする", for: .normal)
                followButton.setTitleColor(.white, for: .normal)
                followButton.backgroundColor = .link
                followButton.layer.borderWidth = 0
            }
        }
        
        override func prepareForReuse() {
            super.prepareForReuse()
            profileImageView.image = nil
            nameLabel.text = nil
            usernameLabel.text = nil
            followButton.setTitle(nil, for: .normal)
            followButton.layer.borderWidth = 0
            followButton.backgroundColor = nil
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            
            profileImageView.frame = CGRect(x: 3,
                                            y: 3,
                                            width: contentView.height-6,
                                            height: contentView.height-6)
            profileImageView.layer.cornerRadius = profileImageView.height/2.0
            
            let buttonWidth = contentView.width > 500 ? 220.0 : contentView.width/3
            followButton.frame = CGRect(x: contentView.width-5-buttonWidth,
                                        y: (contentView.height-40)/2,
                                        width: buttonWidth,
                                        height: 40)
            
            let labelHeight = contentView.height/2
            nameLabel.frame = CGRect(x: profileImageView.right+5,
                                     y: 0,
                                     width: contentView.width-8-profileImageView.width-buttonWidth,
                                     height: labelHeight)
            usernameLabel.frame = CGRect(x: profileImageView.right+5,
                                         y: nameLabel.bottom,
                                         width: contentView.width-8-profileImageView.width-buttonWidth,
                                         height: labelHeight)
            
        }
        
    }
    
    
[/code]

[![エラー箇所](https://i.stack.imgur.com/zT9Yx.png)](https://i.stack.imgur.com/zT9Yx.png)

下記、関連クラスです。

[code]

    import UIKit
    
    class ListViewController: UIViewController {
        
        private let data: [UserRelationship]
            
        private let tableView: UITableView = {
            let tableView = UITableView()
            tableView.register(UserFollowTableViewCell.self,
                               forCellReuseIdentifier: UserFollowTableViewCell.identifier)
            return tableView
        }()
        
        // 初期化
        
        init(data: [UserRelationship]) {
            self.data = data
            super.init(nibName: nil, bundle: nil)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.delegate = self
            tableView.dataSource = self
            view.addSubview(tableView)
            view.backgroundColor = .systemBackground
        }
        
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            tableView.frame = view.bounds
        }
        
    }
    
    extension ListViewController: UITableViewDelegate, UITableViewDataSource {
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return data.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: UserFollowTableViewCell.identifier,
                                                     for: indexPath) as! UserFollowTableViewCell
            
            cell.configure(with: data[indexPath.row])
            return cell
        }
        
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            tableView.deselectRow(at: indexPath, animated: true)
            // 選択したセルのプロフィールへ
            let model = data[indexPath.row]
        }
        
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 75
        }
        
    }
    
[/code]


CC BY-SA 4.0
2020-10-21T04:59:35.883
71371
2020-10-21T07:24:03.907
2020-10-21T07:24:03.907
3060
42090
question
swift ios xcode
エラー Cannot convert value of type 'UserRelationship' to expected argument type 'String'


あなたは、プロトコル`UserFollowTableViewCellDelegate`の中で、メソッド`didTapFollowUnfollowButton(model:)`の引数`model:`を`String`型であると宣言しています。

ところが、エラーが発生している`didTapFollowButton()`の中では、`delegate?.didTapFollowUnfollowButton(model:
model)`のように引数`model:`に対して、`UserRelationship`型の値である`model`を渡しています。

そのためSwiftは、「'UserRelationship'の値(である`model`)を(`didTapFollowUnfollowButton(model:)`の宣言が要求している)'String'に変換できない」と言っているわけです。(変数の名前さえ合わせておけば、適当にうまくやってくれるなんて機能はありません。)

Swiftは強い型付けを行うのが普通のコンパイラ言語の中でも、特に型チェックが厳しく、自動的に型変換を行ってくれることは殆どありません。メソッド宣言中の仮引数の型と実際に呼び出す部分の実引数の型は必ず一致させるようにしてください。

* * *

あなたのコードの場合、`delegate`のメソッドを呼び出すのは、`UserFollowTableViewCell`の中なのですから、その呼び出し方に合わせて`UserFollowTableViewCellDelegate`の宣言の方を修正するのが良いでしょう。

[code]

    protocol UserFollowTableViewCellDelegate: AnyObject {
        func didTapFollowUnfollowButton(model: UserRelationship) //<-
    }
    
[/code]

現在示されているコードの中には、`UserFollowTableViewCellDelegate`プロトコルを実装しているクラスはどこにもありませんが、もし既に実装しているクラスがどこかにあるなら、そこも上の宣言に合わせて修正する必要があります。


CC BY-SA 4.0
2020-10-21T06:27:44.030
71373
2020-10-21T06:27:44.030
13972
71371
answer