1

画像の配列を取得し、画像を並べてスクロールビューを返すライブラリを開発しようとしています。

ただし、メインビューに戻るこのscrollViewを追加しても、画像は追加されません。画像は正しいです。

私のアイデアは、各画像を並べてスクロールビューを使用し、スクローラーを使用してスライドショーのように表示することです。まず、このコンセプトは大丈夫ですか?

第二に、シミュレーターでアプリケーションを実行したときに画像が表示されない理由がわかりません。

詳細が必要な場合はお問い合わせください。

コードは次のとおりです。私のヘッダーファイル:

#import <UIKit/UIKit.h>

@interface HCIImageSlideShowView : UIScrollView

-(void) setImages:(NSArray*) imagesArray;
-(void) setBounds:(CGRect)bounds;
-(void) setCaptions:(NSArray*) imageCaptionsArray;

-(void) isEditable:(BOOL)edit;

-(void) setSlideTime:(int) milliSeconds;

-(void) startSlideShow;

- (id) initWithImages:(NSArray*)imagesArray captionsArray:(NSArray*) captionArray
               bounds:(CGRect)bounds slideTime:(int)milliSeconds;

@end

私の実装ファイル:

#import "HCIImageSlideShowView.h"
#import "HCIResultListViewController.h"

@interface HCIImageSlideShowView ()

@property (strong,nonatomic) NSMutableArray *imagesArray;
@property BOOL editable;
@property (nonatomic)  int slideTime;
@property (strong,nonatomic) NSMutableArray *imageCaptionsArray;
@property CGFloat width;

@end


@implementation HCIImageSlideShowView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (id) initWithImages:(NSArray*)imagesArray captionsArray:(NSArray*) captionArray
               bounds:(CGRect)bounds slideTime:(int)milliSeconds
{

    NSLog([NSString stringWithFormat:@"%f,%f", bounds.size.width , bounds.size.height]);

    CGFloat width_t = bounds.size.width;

    bounds.size.width = [imagesArray count] * bounds.size.width;

    self = [[HCIImageSlideShowView alloc] initWithFrame:bounds];

    _width = width_t;

    [self setBackgroundColor:[[UIColor alloc] initWithRed:0.2 green:0.1 blue:0.3 alpha:0.4]];

     if (self) {
        [self setImages:imagesArray];
        [self setSlideTime:milliSeconds];
        [self setCaptions:captionArray];
        [self defaultLoad];
    }

    self.scrollEnabled = YES;

    return self;
}

-(void) defaultLoad
{

    NSLog([NSString stringWithFormat:@"%f,%f,%f",_width,self.bounds.size.height,self.bounds.size.width]);

    for (int i = 0; i < [_imagesArray count]; i++) {
        CGRect imageBounds = CGRectMake(i * _width, self.bounds.size.height, _width, self.bounds.size.height);
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageBounds];
        [imageView setImage:[HCIResultListViewController resizeImage:_imagesArray[i] withWidth:_width withHeight:self.bounds.size.height]];
        NSLog([NSString stringWithFormat:@"%f,%f",imageView.bounds.size.height,imageView.bounds.size.width]);
        [self addSubview:imageView];
    }

}

-(void) setBounds:(CGRect)bounds
{
    self.bounds = bounds;
}

-(void) setImages:(NSArray *)imagesArray
{
    _imagesArray = [[NSMutableArray alloc] initWithArray:imagesArray];
}

-(void) setSlideTime:(int)milliSeconds
{
    _slideTime = milliSeconds;
}

-(void) startSlideShow
{

}

-(void) isEditable:(BOOL)edit
{
    _editable = edit;
}

-(void) setCaptions:(NSArray *)imageCaptionsArray {
    _imageCaptionsArray = [[NSMutableArray alloc] initWithArray:imageCaptionsArray];
}

@end
4

2 に答える 2

2

コード、特に初期化子に多くの問題があるようです。コメント版はこちら

@interface HCIImageSlideShowView : UIScrollView


-(void) startSlideShow;

- (id) initWithImages:(NSArray*)imagesArray captionsArray:(NSArray*) captionArray
               bounds:(CGRect)bounds slideTime:(int)milliSeconds;
    /*
     remove this custom initialiser as it is quite wrong. 
     Use the default initialiser (don't override) 
     then set the properties after you have created the object. 
     */


    /* Remove all of your custom setters. 
    If any of these properties need setting outside of the class, 
    move the property declarations to the .h file.
    */ 

     -(void) setImages:(NSArray*) imagesArray;
     -(void) setBounds:(CGRect)bounds;
     -(void) setCaptions:(NSArray*) imageCaptionsArray;

     -(void) isEditable:(BOOL)edit;

     -(void) setSlideTime:(int) milliSeconds;

@end



    #import "HCIImageSlideShowView.h"
    #import "HCIResultListViewController.h"

@interface HCIImageSlideShowView()
/*
make these properties public by moving them to your .h file 
so that you can set them from the calling object
*/
@property (strong,nonatomic) NSMutableArray *imagesArray;
@property BOOL editable;
@property (nonatomic)  int slideTime;
@property (strong,nonatomic) NSMutableArray *imageCaptionsArray;
@property CGFloat width;
@end

@implementation HCIImageSlideShowView

 - (id) initWithImages:(NSArray*)imagesArray captionsArray:(NSArray*) captionArray
               bounds:(CGRect)bounds slideTime:(int)milliSeconds
/*
     You seem to be getting confused with init, 
     so I suggest you do not make a custom init method at all. 
     Initialise your object with the default initWithFrame, 
     then have the caller set properties on your newly 
         made object after initiliasation.

*/

{
     NSLog([NSString stringWithFormat:@"%f,%f", bounds.size.width , bounds.size.height]);
    /*
      This is the way to use NSLog...
      NSLog(@"%f,%f", bounds.size.width , bounds.size.height);
     */

    CGFloat width_t = bounds.size.width;
    /*
     double assignment: two lines further down you assign 
    width_t to _width. You can do that here in one step
     */

    bounds.size.width = [imagesArray count] * bounds.size.width;

    self = [[HCIImageSlideShowView alloc] initWithFrame:bounds];

    /*
     This is wrong. Although as Hermann says it may be _legal_, don't do it!
         -Never alloc an object inside it's own initialiser. 
         The memory will already have been alloc'd by the caller. 
         - Never assign to self anything but the return value from super's init.
     */

    _width = width_t;

    /*
     please be consistent with your iVar/property naming. 
     Here you are addressing the ivar _width, 2 lines up 
     you are using the property accessor syntax self.bounds. 
     In you case I would recommend ALWAYS using self.varName 
     except inside a custom setter or getter. 
     */

    [self setBackgroundColor:[[UIColor alloc] initWithRed:0.2 green:0.1 blue:0.3 alpha:0.4]];

    if (self) {
            //[self setImages:imagesArray];
        self.imagesArray = [imagesArray mutableCopy];

            //[self setSlideTime:milliSeconds];
        self.slideTime = milliSeconds;

            //[self setCaptions:captionArray];
        self.imageCaptionsArray = [captionArray mutableCopy];

        /*
         As my comment above - use property syntax and try to 
         avoid writing your own setters and getters 
         unless you have a very good reason.
         */

        [self defaultLoad];
    }

    self.scrollEnabled = YES;

    return self;
}

あなたの初期化コードにはいくつかの再配置が必要なので、私はあまり詳しく見ていませんでしたdefaultLoadが、いくつかの観察があります...

(1)

CGRect imageBounds = CGRectMake(i * _width, self.bounds.size.height, _width, self.bounds.size.height);

する必要があります

    CGRect imageBounds = CGRectMake(i * _width,0, _width, self.bounds.size.height);

そうしないと、画像はすべて scrollView の高さの下で画面外に配置されます。

(2)

scrollView がスクロールできるように contentSize を設定する必要があります

[scrollView setContentSize:(CGSize){self.width*[imageArray count],self.bounds.size.height}];

もう1つのより一般的なコメントは、これはいくつかの画像では問題ないということですが、メモリを消費するため、オフスクリーンのimageViewの大規模な配列でscrollViewを作成したくないということです。実際に必要なのは、現在画面に表示されている画像と、左右の前後の画像の 3 つだけです。アイデアは、必要な場合にのみ画像をロードし、tableView が機能するのと同じように imageView をリサイクルすることです。

付属の WWDC 2010/11 ビデオとスライドと共に、 Apple の Photoscroller サンプル アプリをご覧ください。

タイリングとズームのすべての詳細について心配する必要はありません。オブジェクトの作成を最小限に抑え、可能な場合はオブジェクトをリサイクル/再利用するという一般原則を理解することをお勧めします。

ところで、カスタム scrollView オブジェクトはまったく必要ない場合があります。呼び出し元の viewController オブジェクトから数行のコードで目的のほとんどを実現できます。例えば...

- (void) viewDidLoad {
        [super viewDidLoad];
    UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    [scrollView setBackgroundColor:[UIColor redColor]];
    NSArray* imageArray = @[[UIImage imageNamed:@"image1.png"]
                            ,[UIImage imageNamed:@"image2.png"]
                            ,[UIImage imageNamed:@"image3.png"]
                            ];
    CGFloat width = scrollView.bounds.size.width;
    CGFloat height = scrollView.bounds.size.height;

    for (int i = 0; i < [imageArray count]; i++) {
        CGRect imageFrame = CGRectMake(i * width, 0, width, height);
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
        [imageView setImage:imageArray[i]];
        [scrollView addSubview:imageView];
    }
    [scrollView setContentSize:(CGSize){width*[imageArray count],height}];
    [self.view addSubview:scrollView];
}
于 2013-03-18T16:08:33.263 に答える
0
- (id) initWithImages:(NSArray*)imagesArray captionsArray:(NSArray*) captionArray
               bounds:(CGRect)bounds slideTime:(int)milliSeconds
{

    NSLog([NSString stringWithFormat:@"%f,%f", bounds.size.width , bounds.size.height]);

    CGFloat width_t = bounds.size.width;

    bounds.size.width = [imagesArray count] * bounds.size.width;

    self = [self initWithFrame:bounds];

    _width = width_t;

    [self setBackgroundColor:[[UIColor alloc] initWithRed:0.2 green:0.1 blue:0.3 alpha:0.4]];

     if (self) {
        [self setImages:imagesArray];
        [self setSlideTime:milliSeconds];
        [self setCaptions:captionArray];
        [self defaultLoad];
    }

    self.scrollEnabled = YES;

    return self;
}
于 2013-03-18T14:11:23.517 に答える