Reputation: 5256
I'm trying to develop a library which takes an array of images and returns a scrollView with the images each side by side.
However when I add this scrollView, which I'm returning to my main view, it doesn't add the images. Images are correct.
My idea is to use a scrollview with each image side by side and using the scroller to show like a slide show. Firstly, is this concept okay?
Secondly, I do not understand why the images are not shown when I run the application in the simulator.
Any more details required please ask.
The code is as follows. My header file :
#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
My implementation file:
#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
Upvotes: 1
Views: 126
Reputation: 31745
There seems to be a lot wrong with your code - especially your initialiser. Here is a commented version
@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;
}
As your initialisation code needs some rearranging, I did not look too closely at defaultLoad
- however I do have a couple of observations...
(1)
CGRect imageBounds = CGRectMake(i * _width, self.bounds.size.height, _width, self.bounds.size.height);
Should be
CGRect imageBounds = CGRectMake(i * _width,0, _width, self.bounds.size.height);
Otherwise your images are all placed offscreen beneath your scrollView's height.
(2)
You need to set a contentSize so that the scrollView can scroll
[scrollView setContentSize:(CGSize){self.width*[imageArray count],self.bounds.size.height}];
The other more general comment is that this is OK for a few images, but you wouldn't want to be making a scrollView with a large array of offscreen imageViews as you will eat up memory. You actually only need three, for the image currently on screen, and the previous and next images to the left and right. The idea is to load your images only when you may need them, and recycle your imageViews much the way a tableView works.
You should take a look at Apple's Photoscroller sample app along with it's accompanying WWDC 2010/11 video(s) and slides
Don't worry about all of the details on tiling and zooming, it's good to get the general principle of keeping object creation to a minimum and recycling/reusing objects where feasible.
By the way, you may not need a custom scrollView object at all: you can achieve most of what you are after in a few lines of code from your calling viewController object. eg...
- (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];
}
Upvotes: 2
Reputation: 14068
- (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;
}
Upvotes: 0