0

私のiPadアプリには、2つのUIScrollviewと1つのUIPageControlを含むメインのViewControllerがあります。問題は、ページングのデリゲートが呼び出されないことです。レイアウトは次のとおりです。

ここに画像の説明を入力してください

下のthumbScrollViewでボタンを選択すると、mainScrollViewの画像が更新される必要があります(これは機能します)thumbScrollViewをスワイプするか、pageControlでドットを選択すると、thumbScrollViewを「ページング」して、次の前のボタンのセットを表示する必要があります。デリゲート関数が呼び出されないため、スワイプは機能しません。

VCで次のようにスクロールビューとページコントロールを宣言します

@property (strong, nonatomic) IBOutlet UIScrollView *mainScrollView;
@property (strong, nonatomic) IBOutlet UIScrollView *thumbScrollView;
@property (strong, nonatomic) IBOutlet UIPageControl *pageControl;

ViewControllerはUIScrollViewDelegateを実装します

@interface MyViewController : UIViewController<UIScrollViewDelegate>

そして、次のUIScrollViewDelegateデリゲート関数をVCの.mファイルに実装します。

- (void)scrollViewDidScroll:(UIScrollView *)sender;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

ビューは表示されますが、ボタンをスワイプすると、上記のデリゲート関数が呼び出されません。

StackOverflowでこれに対する解決策を見つけられませんでしたが、これの他の側面について他の関連する投稿からのアドバイスを考慮しました(たとえば、どのスクロールビューがアクションを開始したかを区別するロジックなど)

ここに詳細なコードを追加する(@HeWasからの要求に応じて)

これは、2つのスクロールビューとページコントロールを制御するメインビューコントローラーのヘッダーファイルです(関連する抜粋-さらに必要な場合は教えてください)

// ImageBrowseViewController.h
// (NOTE - In Interface Builder I have added a tag attribute of 0 to mainScrollView
//  and 1 to thumbScrollView, to enable me to distinguish which scrollView the delegate 
//  needs to respond to)



#define TAG_MAIN_SCROLLVIEW 0
#define TAG_THUMB_SCROLLVIEW 1

@interface ImageBrowseViewController : UIViewController<UIScrollViewDelegate>
{
    UIButton* currentlySelectedButton;
    UIScrollView *mainScrollView;
    UIScrollView *thumbScrollView;
    UIPageControl* pageControl;
    BOOL pageControlBeingUsed;

}

@property (strong, nonatomic) IBOutlet UIScrollView *mainScrollView;
    // … connected as outlet in IB to mainScrollView
@property (strong, nonatomic) IBOutlet UIScrollView * thumbScrollView;
    // … connected as outlet in IB to thumbScrollView
@property (strong, nonatomic) IBOutlet UIPageControl *pageControl;
    // … connected as outlet in IB to pageControl


…
-(IBAction)changePage; //Touch up Inside IBAction connected to pageControl


…
@end

これは、2つのスクロールビューとページコントロールを制御するメインビューコントローラーの実装ファイルです(関連する抜粋-さらに必要な場合は教えてください)

//
//  ImageBrowseViewController.m
//

    …
@synthesize mainScrollView;
@synthesize thumbScrollView;
@synthesize pageControl;


// UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)sender {

    if ( [sender tag] == TAG_THUMB_SCROLLVIEW ) {
        // This is the thumbScrollview
        // Update the page when more than 50% of the previous/next page is visible

        CGFloat pageWidth = self.thumbScrollView.frame.size.width;
        int page = 
            floor((self.thumbScrollView.contentOffset.x - pageWidth / 2) / pageWidth) 
            + 1;
        self.pageControl.currentPage = page;

    }
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    pageControlBeingUsed = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    pageControlBeingUsed = NO;
}

- (IBAction)changePage {
    // Update the scroll view to the appropriate page
    CGRect frame;
    //frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
    frame.origin.x = self.thumbScrollView.frame.size.width * self.pageControl.currentPage;

    frame.origin.y = 0;
    frame.size = self.thumbScrollView.frame.size;
    [self.thumbScrollView scrollRectToVisible:frame animated:YES];

    // Keep track of when scrolls happen in response to the page control
    // value changing. If we don't do this, a noticeable "flashing" occurs
    // as the the scroll delegate will temporarily switch back the page
    // number.
    pageControlBeingUsed = YES;
}
4

1 に答える 1

1

コードはすべて 100% に見えます (このタイプミスは別として:@synthesize floorplanThumbScrollView;ですが、それは問題ではありません)。

答えは、IBでスクロールビューDELEGATESを正しく配線していないことだと確信しています。

これが手がかりです:

「はい、Interface Builder で 3 つすべてを設定しました。したがって、mainScrollView、thumbScrollView、および pageControl は、VC の .h ファイルの上記の宣言に IB で接続されています。」

ViewController と scrollViews の間に 2 つの接続が必要です。

(1) Ctrl キーを押しながら viewController から scrollView にドラッグし、IBOutlet プロパティに接続します。
これはあなたがしたことです。

(2) Ctrl キーを押しながら scrollView から viewController にドラッグし、 に接続しdelegateます。
私はあなたがこれをしたとは思わない。

ステップ2の説明

UIScrollView には、「delegate」という組み込みプロパティがあります。scrollView はこのプロパティを使用して、そのデリゲートにメッセージを送信します。このデリゲートは、インターフェイス ビルダー (手順 2) で設定するか、コードで設定できます。たとえば、viewController でこれを行うことができます。

    [myScrollView setDelegate:self];

これにより、viewController が myScrollView のデリゲートとして設定されます。Interface Builder でリンクして行う場合、このコードは必要ありません (そして IB はコードを作成しません)。

いずれにせよ、これが実際に行うことは、scrollView のデリゲート iVar を viewController へのポインタに設定することです。このようなデリゲートを使用することの優れた点は、デリゲート (UIScrollView) がデリゲート先 (この場合は UIViewController) について何も知る必要がないことです。これにより、UIScrollView がデリゲート プロトコルであることを確認している限り、UIScrollView を再利用できます。

scrollView がデリゲートであることを通知する必要がある場合は常に、内部的に次のようなメッセージを送信します。

    [self.delegate scrollViewDidScroll:self];

(それはわかりません。scrollView の実装にあります)。

scrollView のデリゲートとして設定したオブジェクトは、scrollView のデリゲート プロトコルが宣言するすべての必須メソッドを実装する必要があり、任意のデリゲート メソッドの実装を選択できます。 ここにプロトコルがあります

どのメソッドが必要かを判断するには、UIScrollView クラス リファレンスを読んでください。

UIScrollView クラスには、UIScrollViewDelegate プロトコルを採用する必要があるデリゲートを含めることができます。ズームとパンが機能するには、デリゲートは と の両方を実装する必要がviewForZoomingInScrollView:ありscrollViewDidEndZooming:withView:atScale:ます。さらに、最大 ( maximumZoomScale) と最小 ( minimumZoomScale) のズーム スケールは異なる必要があります。

プロトコルの他のすべてはオプションです。

このデリゲート パターンは、独自のオブジェクトを再利用するために簡単に実装できるものであり、Objective-C で分離されたオブジェクト間でメッセージを渡す最も一般的な方法の 1 つです。

于 2013-01-10T17:55:11.070 に答える