質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

スクロールビューのcontentOffset.xの値がずっと0【Xcode12.0.1】

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 323

score 2

前提・実現したいこと

前提:
・ScrollViewの横スクロールにおいて、増減するはずのscrollView.contentOffset.xの値がずっと0のままである。
・ストーリボードを最小限しか使わず、ほぼ全てSnapKitによるセットアップをしている。そうではない場合(オートレイアウトを使う場合)、値はちゃんと増減する。

実現したいこと:上記を改善したい。

イメージ説明

このように、横にスクロールしているのにもかかわらずプリントされるのは0である。

該当のソースコード(必要最低限)

import UIKit

let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height
import UIKit
import SnapKit

//MARK:- Class_ViewController
class FirstViewController: UIViewController {

    let horizontalScrollView = UIScrollView()
    let superStackView = UIView()
    let stackView = UIStackView()
    var tableViews = [UITableView]()

    override func viewDidLoad() {
        super.viewDidLoad()

        setUpViews()
    }

    //MARK: View
    private func setUpViews() {
        //addViews
        view.addSubview(horizontalScrollView)
        horizontalScrollView.addSubview(superStackView)
        superStackView.addSubview(stackView)
        for _ in 0..<4 {
            let tableView = UITableView()
            tableViews.append(tableView)
            stackView.addArrangedSubview(tableView)
        }

        //setUpConstrains
        view.frame.size = CGSize(width:  width * 4, height: height)
        horizontalScrollView.snp.makeConstraints { make in
            make.width.equalToSuperview()
            make.height.equalToSuperview()
            make.edges.equalToSuperview()
        }
        [superStackView, stackView].forEach {
            $0?.snp.makeConstraints { make in
                make.height.equalToSuperview()
                make.edges.equalToSuperview()
            }
        }
        tableViews.forEach {
            $0.snp.makeConstraints { make in
                make.width.equalTo(horizontalScrollView.snp.width)
                make.top.equalTo(300)
            }
        }

        //MARK: setUpInspetors
        horizontalScrollView.backgroundColor = .black
        horizontalScrollView.isPagingEnabled = true
        superStackView.backgroundColor = .darkGray
        stackView.backgroundColor = .gray
        stackView.axis = .horizontal
        stackView.alignment = .fill
        stackView.distribution = .fillEqually
        tableViews.forEach {
            $0.delegate = self
            $0.dataSource = self
            $0.backgroundColor = .lightGray
        }
    }
}

//MARK:- Extension_UITableView
extension FirstViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: nil)

        let text = ["👽","💀","😻","🙀","🤖","🎃","🤟","🐰","🐹"][Int(arc4random() % 9)]
        cell.textLabel?.text = text
        cell.backgroundColor = .white

        return cell
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {

        //ここのプリントで、xがずっと0のまま出力される
        print(scrollView.contentOffset)

        if (scrollView == self.horizontalScrollView) {
            //また、scrollView がなぜか決して horizontalScrollView にならない(IBフル使用時はちゃんとなる)
            horizontalScrollHyps(scrollView)
        }
        else {
            verticalScrollHyps(scrollView)
        }
    }

    private func horizontalScrollHyps(_ scrollView: UIScrollView) {
        //横スクロールでの処理
    }

    private func verticalScrollHyps(_ scrollView: UIScrollView) {
        //縦スクロールでの処理
    }
}

やっていることは

スクロールビューの上にスタックビューの土台を乗せる
スタックビューの土台の上にスタックビューを乗せる
スタックビューの上にテーブルビューを乗せる

というのと、それらのConstraintの設定です。これをStoryboardを使用した場合で(AutoLayout以外を)表現するとこうなります。

イメージ説明

このStoryBoard版だと、普通に問題はありません。

試したこと

・諸々の再起動
・Constraintの複数パターンでの再設定
translatesAutoresizingMaskIntoConstraintsをtrueにしたりfalseにしたりした。ただ、trueにすると余計ぐちゃぐちゃになるのでやめた。

その他、Googleで調べ続け細かい補正などを一ヶ月近くやって悉く失敗。
回答よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

MacOS Catalina バージョン10.15.6
Xcode12.0.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tsuki01

    2020/10/04 00:12

    提示されているコードのままですといくつかエラーが発生したり、検証に必要な処理が足りて無い気がするのですがいかがでしょうか。
    以下の点を修正して頂けると回答が付きやすくなるかと思いますので、対応のほどご検討ください。

    ・31行目:「width、height」 の定義が不足している(エラー発生)
    ・46行目:「profileView」 の定義が不足している(エラー発生)
    ・ScrollViewのDelegate設定が不足している(スクロール後のデバッグとして必要ではないか)
    ・「scrollView.contentOffset.x」の値を確認する際は、どこのイベントでログ出力して確認しているか?(ログ出力の処理も追加した方が良いかと思います)

    キャンセル

  • Zhalen

    2020/10/04 11:21

    はい、すいません。見落としでした🙇🏻‍♂️
    間もなく修正致します。

    キャンセル

  • tsuki01

    2020/10/04 13:37 編集

    修正ありがとうございました。更に以下を追記して実行してみたら「contentOffset.x」の値が問題なく出力されておりました。こちらの確認方法が誤っていたら申し訳ありませんが、共有いたします(コメント内の"horizontalScrollView にならない"に関しても動作していた)

    ・追記処理
     UIScrollViewDelegateプロトコルの追加
     horizontalScrollViewに対するDelegate指定

    ・こちらの検証環境
     Xcode11.2.1 + iPhone11ProMaxシミュレータ

    キャンセル

  • Zhalen

    2020/10/04 14:09

    うああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああアアアアアアアアアア!!!!!!!!!!!!!!!!!!!!(欣喜雀躍)

    正常に動作しました! もしかしたらストーリーボードを使う場合、スクロールビューを配置した時点でUIScrollViewDelegateが自動で組み込まれてたからその違いに気づけなかったんだと思いました。

    はアアアアアアアアアアああ!!!!!!!! 間接的ではありますが(恐らく)命を救って頂き誠に感謝いたします! 感謝! 謝謝! Gracias!!! 🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️🙇🏻‍♂️

    キャンセル

回答 1

check解決した方法

0

tsuki01様のおかげで、無事解決することができました! 本当にありがとうございます! 

【改善方法】
1、エクステンションで以下を記述する。

extension FirstViewController: UIScrollViewDelegate {
    //中身は何もなくてよい
}

2、スクロールビューをデリゲートさせる。(今回の場合はhorizontalScrollView

        //MARK: setUpInspetors
        horizontalScrollView.delegate = self //ここを追加
        (以下略)

3、起動
イメージ説明

【考えられる原因】
恐らく、Interface Builder(Storyboard)を使ってスクロールビューを配置した時点で、UIScrollViewDelegateが組み込まれている。これは他のいくつかのViewに関しても同様なものがあると思われる。Googleでいくら調べてもこんな事書いてなかったぞ……
もしかしたら上級者の方からすれば自明な事だったかも知れませんが、また新たな知識を得ることができました。

再三になりますが、本当にtsuki01様ありがとうございました!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/04 20:29

    無事に動作するようになったとのことで良かったです。
    私も正確に理解していないのですが、以下の点だけ異なるかと思うので補足させて頂きます。

    >恐らく、Interface Builder(Storyboard)を使ってスクロールビューを配置した時点で、>UIScrollViewDelegateが組み込まれている。

    こちらに関してですが、自動でDelegateが組み込まれることは無い(はずです。。)
    TableView自体がScrollViewを継承しているので、TableViewDelegate側でScrollViewのDelegateを拾ってくれているのかもしれません。
    実際、「UIScrollViewDelegate」を追加しなくても「func scrollViewDidScroll(_ scrollView: UIScrollView)」が呼ばれることを確認できました。

    ※曖昧なコメントとなってしまったので、「そうなんだ」程度に流して頂けると幸いです。

    キャンセル

  • 2020/10/05 09:22

    そうだったのですね。そうか...テーブルビューに継承されているのならば、やはりなぜストーリーボードを使わなくなっただけでこのような差異が出るのか本当に分からないですね。うーむ......謎だ。
    それかもしかしたら単に私自身のミスで、今回のSnapKit使用版で新しくプロジェクトを書き上げていった際に以前付け加えていたはずの微細な因子を見逃してしまっていたのかも知れません。厳密に精査しながら絶対に違いが出ないようにやっていた為こちらも考えにくいですが、今後、状況が判明次第逐次追記していくと思います。
    コメントありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る