I am currently dynamically adding a UIImage to my UIScrollView object and everything is working as intended. I need to add extra functionality now (a UIActivityIndicator in the center of the image when it is loading from the internet, and a label underneath) so I thought why not create a custom View which has all of these laid out as I need them to be, and then just load it into the scrollView. I have encountered a problem though, when I add it to the scrollView, nothing shows up. Here is what I have:
我目前正在动态地向我的UIScrollView对象添加一个UIImage,一切都按预期工作。我现在需要添加额外的功能(当它从互联网加载时,UIActivityIndicator位于图像的中心,下面是一个标签)所以我想为什么不创建一个自定义视图,其中包含所有这些,因为我需要它们是,然后只需将其加载到scrollView中。我遇到了一个问题,当我将它添加到scrollView时,没有任何显示。这是我有的:
NewsViewController.m:
NewsViewController.m:
imageScrollView.contentSize = CGSizeMake(320*numberOfPages, 303);
pageControl.numberOfPages = numberOfPages;
dispatch_queue_t imageDownload = dispatch_queue_create("imageDownload", NULL);
__block NSData *temp;
CustomImageView *customImageView = [[CustomImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 303)];
[imageScrollView addSubview:customImageView];
[[customImageView activityIndicator] startAnimating];
dispatch_async(imageDownload, ^{
temp = [[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.wlfarm.org/wp-content/uploads/2012/05/farm.jpg"]]retain];
dispatch_async(dispatch_get_main_queue(), ^{
customImageView.imageView.image = [[UIImage alloc] initWithData:temp];
[[customImageView activityIndicator] stopAnimating];
[customImageView setNeedsDisplay];
customImageView.caption.text = @"HAHAHAHAHHAHA";
[imageScrollView setNeedsDisplay];
[temp release];
});
});
dispatch_release(imageDownload);
CustomImageView.h:
CustomImageView.h:
#import <UIKit/UIKit.h>
@interface CustomImageView : UIView
{
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) IBOutlet UILabel *caption;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
@end
CustomImageView.m
CustomImageView.m
#import "CustomImageView.h"
@interface CustomImageView ()
@end
@implementation CustomImageView
@synthesize caption, imageView, activityIndicator;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
I am including a screenshot of my XIB file, and the program running on the simulator. The first picture shows nothing in the scrollView(the attempt made by using my custom class), and the second page of the scroll view is the attempt made by adding a UIImageView to the UIScrollView(which worked). Can anyone point out what I am doing wrong? Am I not allowed to load a custom view into a UIScrollView? Thanks for your help!
我包括我的XIB文件的屏幕截图,以及在模拟器上运行的程序。第一张图片在scrollView(通过使用我的自定义类进行的尝试)中没有显示任何内容,滚动视图的第二页是通过向UIScrollView(工作)添加UIImageView进行的尝试。谁能指出我做错了什么?我不允许将自定义视图加载到UIScrollView中吗?谢谢你的帮助!
IB Screenshot - http://i.stack.imgur.com/gz9UL.png
IB截图 - http://i.stack.imgur.com/gz9UL.png
iOS Simulator No Image with CustomView Screenshot - http://i.stack.imgur.com/zhswq.png
iOS模拟器无图像与CustomView截图 - http://i.stack.imgur.com/zhswq.png
iOS Simulator Image with UIImageView Screenshot - http://i.stack.imgur.com/97vmU.png
iOS模拟器图像与UIImageView截图 - http://i.stack.imgur.com/97vmU.png
2 个解决方案
#1
1
It looks as though CustomImageView
is a subclass on UIViewController
, not UIImageView
or UIView
. You can't add a UIViewController
as a subview like that. change it to subclass UIView
and it should work.
看起来好像CustomImageView是UIViewController上的子类,而不是UIImageView或UIView。你不能像这样添加UIViewController作为子视图。将它更改为子类UIView,它应该工作。
To load a UIView
from a .nib, you need to declare your IBOutlet
properties as you would for a UIViewController
. Define the correct custom class in IB and connect everything up, including the base view. Then override the following method inside your custom view class.
要从.nib加载UIView,您需要像对UIViewController一样声明您的IBOutlet属性。在IB中定义正确的自定义类并连接所有内容,包括基本视图。然后在自定义视图类中覆盖以下方法。
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
It seems you have cut and pasted methods from a UIViewController
subclass into you UIView
subclass. Start by deleting all the methods you've pasted in between @synthesize
and @end
. A UIView
subclass requires different methods to to load from a .nib, so you need to override the method shown above instead and use the line of code
您似乎已将UIViewController子类中的方法剪切并粘贴到UIView子类中。首先删除@synthesize和@end之间粘贴的所有方法。 UIView子类需要从.nib加载不同的方法,因此您需要覆盖上面显示的方法并使用代码行
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[[NSBundle mainBundle] loadNibNamed:@“
to load the nib.
加载笔尖。
Further to your comment about connecting the base view, here is what I mean:
关于连接基本视图的评论,这就是我的意思:
After creating your custom class and nib file, open the nib and highlight "Files Owner" on the left, then on the top right hand side, select the icon 3rd from the left, looks like an ID card or something. In the "Class" box, add the name of your custom class.
创建自定义类和nib文件后,打开笔尖并突出显示左侧的“文件所有者”,然后在右上角,从左侧选择第3个图标,看起来像ID卡或其他内容。在“类”框中,添加自定义类的名称。
In your customClass, add an IBOutlet UIView
property called baseView, and add a UIView that covers the view in IB at the root level, connect these two. Then add everything else on top of that
在customClass中,添加一个名为baseView的IBOutlet UIView属性,并在根级别添加一个覆盖IB视图的UIView,将这两个连接起来。然后在其上添加其他所有内容
you code would now look something like this:
您的代码现在看起来像这样:
CustomImageView.h
CustomImageView.h
#import <UIKit/UIKit.h>
@interface CustomImageView : UIView
{
IBOutlet UIView *baseView
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
@property (nonatomic, retain) IBOutlet UIView *baseView;
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) IBOutlet UILabel *caption;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
@end
CustomImageView.m
CustomImageView.m
#import "CustomImageView.h"
@interface CustomImageView ()
@end
@implementation CustomImageView
@synthesize baseView, caption, imageView, activityIndicator;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.baseView];
}
return self;
}
@end
Provided you connect it all up in IB it should work fine, just remember to add the baseView
如果你在IB中连接它,它应该工作正常,只需记住添加baseView
#2
0
As mentioned earlier initWithNibName
belongs to controllers.
As I think, you're going the wrong way.
如前所述,initWithNibName属于控制器。我认为,你走错了路。
you have a ViewController and want to add a customView, to load dynamically a image from URLData.
你有一个ViewController,并希望添加一个customView,从URLData动态加载图像。
You have 2 Options:
Option 1: Do everything in IB:
In Interfacebuilder edit/(or add a new one) the ViewController's XIB File and add the views that you like. The file's owner is a UIViewController Class/Subclass. Do everything like you did before, except doing it in the view controller. In your App delegate initWithNibName your ViewController like so
您有2个选项:选项1:在IB中执行所有操作:在Interfacebuilder中编辑/(或添加新的)ViewController的XIB文件并添加您喜欢的视图。该文件的所有者是UIViewController类/子类。做你以前做的所有事情,除了在视图控制器中做。在你的App委托initWithNibName你的ViewController就像这样
self.viewController = [[testViewController alloc] initWithNibName:@"testViewController" bundle:nil];
If you want to, initialize your own view controller, which you like to push and push it in the stack.
如果您愿意,请初始化您自己的视图控制器,您希望将其推入并将其推入堆栈中。
What you're doing wrong: You are initializing a customImageView with a Frame, but the nib doesn't get loaded automatically. The Properties are there, but the nib isn't.
您做错了什么:您正在使用Frame初始化customImageView,但是nib不会自动加载。属性在那里,但笔尖不是。
If you really want a stable thing choose
Option 2: Do everything programatically (It is easier, more understanding and lightweight):
From your implementation we do the following:
如果你真的想要一个稳定的东西选择选项2:以编程方式执行所有操作(更容易,更理解和轻量级):从您的实现中我们执行以下操作:
NewsViewController.m
NewsViewController.m
Do like you did before!!!
像你之前做的那样!
CustomImageView.h:
CustomImageView.h:
#import <UIKit/UIKit.h>
@interface CustomImageView : UIView
{
UIImageView *imageView;
UILabel *caption;
UIActivityIndicatorView *activityIndicator;
}
@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, retain) UILabel *caption;
@property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
@end
CustomImageView.m:
CustomImageView.m:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
caption = [[UILabel alloc] initWithFrame:CGRectMake(0, 250, 320, 50)];
[caption setBackgroundColor:[UIColor greenColor]];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 250)];
[imageView setBackgroundColor:[UIColor blueColor]];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.frame = CGRectMake(320/2-25, 460/2-25, 50, 50);
[self.activityIndicator startAnimating];
[self addSubview:self.caption];
[self addSubview:self.imageView];
[self addSubview:self.activityIndicator];
}
return self;
}
Then do everything you did before. That would do a better job
然后做你以前做过的一切。那样做会更好
#1
1
It looks as though CustomImageView
is a subclass on UIViewController
, not UIImageView
or UIView
. You can't add a UIViewController
as a subview like that. change it to subclass UIView
and it should work.
看起来好像CustomImageView是UIViewController上的子类,而不是UIImageView或UIView。你不能像这样添加UIViewController作为子视图。将它更改为子类UIView,它应该工作。
To load a UIView
from a .nib, you need to declare your IBOutlet
properties as you would for a UIViewController
. Define the correct custom class in IB and connect everything up, including the base view. Then override the following method inside your custom view class.
要从.nib加载UIView,您需要像对UIViewController一样声明您的IBOutlet属性。在IB中定义正确的自定义类并连接所有内容,包括基本视图。然后在自定义视图类中覆盖以下方法。
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
It seems you have cut and pasted methods from a UIViewController
subclass into you UIView
subclass. Start by deleting all the methods you've pasted in between @synthesize
and @end
. A UIView
subclass requires different methods to to load from a .nib, so you need to override the method shown above instead and use the line of code
您似乎已将UIViewController子类中的方法剪切并粘贴到UIView子类中。首先删除@synthesize和@end之间粘贴的所有方法。 UIView子类需要从.nib加载不同的方法,因此您需要覆盖上面显示的方法并使用代码行
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[[NSBundle mainBundle] loadNibNamed:@“
to load the nib.
加载笔尖。
Further to your comment about connecting the base view, here is what I mean:
关于连接基本视图的评论,这就是我的意思:
After creating your custom class and nib file, open the nib and highlight "Files Owner" on the left, then on the top right hand side, select the icon 3rd from the left, looks like an ID card or something. In the "Class" box, add the name of your custom class.
创建自定义类和nib文件后,打开笔尖并突出显示左侧的“文件所有者”,然后在右上角,从左侧选择第3个图标,看起来像ID卡或其他内容。在“类”框中,添加自定义类的名称。
In your customClass, add an IBOutlet UIView
property called baseView, and add a UIView that covers the view in IB at the root level, connect these two. Then add everything else on top of that
在customClass中,添加一个名为baseView的IBOutlet UIView属性,并在根级别添加一个覆盖IB视图的UIView,将这两个连接起来。然后在其上添加其他所有内容
you code would now look something like this:
您的代码现在看起来像这样:
CustomImageView.h
CustomImageView.h
#import <UIKit/UIKit.h>
@interface CustomImageView : UIView
{
IBOutlet UIView *baseView
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
@property (nonatomic, retain) IBOutlet UIView *baseView;
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) IBOutlet UILabel *caption;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
@end
CustomImageView.m
CustomImageView.m
#import "CustomImageView.h"
@interface CustomImageView ()
@end
@implementation CustomImageView
@synthesize baseView, caption, imageView, activityIndicator;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:@"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.baseView];
}
return self;
}
@end
Provided you connect it all up in IB it should work fine, just remember to add the baseView
如果你在IB中连接它,它应该工作正常,只需记住添加baseView
#2
0
As mentioned earlier initWithNibName
belongs to controllers.
As I think, you're going the wrong way.
如前所述,initWithNibName属于控制器。我认为,你走错了路。
you have a ViewController and want to add a customView, to load dynamically a image from URLData.
你有一个ViewController,并希望添加一个customView,从URLData动态加载图像。
You have 2 Options:
Option 1: Do everything in IB:
In Interfacebuilder edit/(or add a new one) the ViewController's XIB File and add the views that you like. The file's owner is a UIViewController Class/Subclass. Do everything like you did before, except doing it in the view controller. In your App delegate initWithNibName your ViewController like so
您有2个选项:选项1:在IB中执行所有操作:在Interfacebuilder中编辑/(或添加新的)ViewController的XIB文件并添加您喜欢的视图。该文件的所有者是UIViewController类/子类。做你以前做的所有事情,除了在视图控制器中做。在你的App委托initWithNibName你的ViewController就像这样
self.viewController = [[testViewController alloc] initWithNibName:@"testViewController" bundle:nil];
If you want to, initialize your own view controller, which you like to push and push it in the stack.
如果您愿意,请初始化您自己的视图控制器,您希望将其推入并将其推入堆栈中。
What you're doing wrong: You are initializing a customImageView with a Frame, but the nib doesn't get loaded automatically. The Properties are there, but the nib isn't.
您做错了什么:您正在使用Frame初始化customImageView,但是nib不会自动加载。属性在那里,但笔尖不是。
If you really want a stable thing choose
Option 2: Do everything programatically (It is easier, more understanding and lightweight):
From your implementation we do the following:
如果你真的想要一个稳定的东西选择选项2:以编程方式执行所有操作(更容易,更理解和轻量级):从您的实现中我们执行以下操作:
NewsViewController.m
NewsViewController.m
Do like you did before!!!
像你之前做的那样!
CustomImageView.h:
CustomImageView.h:
#import <UIKit/UIKit.h>
@interface CustomImageView : UIView
{
UIImageView *imageView;
UILabel *caption;
UIActivityIndicatorView *activityIndicator;
}
@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, retain) UILabel *caption;
@property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
@end
CustomImageView.m:
CustomImageView.m:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
caption = [[UILabel alloc] initWithFrame:CGRectMake(0, 250, 320, 50)];
[caption setBackgroundColor:[UIColor greenColor]];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 250)];
[imageView setBackgroundColor:[UIColor blueColor]];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.frame = CGRectMake(320/2-25, 460/2-25, 50, 50);
[self.activityIndicator startAnimating];
[self addSubview:self.caption];
[self addSubview:self.imageView];
[self addSubview:self.activityIndicator];
}
return self;
}
Then do everything you did before. That would do a better job
然后做你以前做过的一切。那样做会更好