iOS: assigning a class to a xib, and not recognizing it - objective-c

I'm using the following code to load a xib in my UIView subclass named ImageWithCaptionView.
I've specified in the xib Inspector the name of the view: ImageWithCaptionView.
However the if statement (isKindOfClass) is never true, and I've to remove it to make things work. What am I missing here ?
UINib *nib = [[UINib nibWithNibName:NSStringFromClass([ImageWithCaptionView class]) bundle:nil] retain];
NSArray *myArray = [nib instantiateWithOwner:self options:nil];
for (id currentObject in myArray) {
if ([currentObject isKindOfClass:[ImageWithCaptionView class]]) {
self = (ImageWithCaptionView *) currentObject;
break;
}
}

Check if the class is also set in the Custom Class field in the identity inspector tab.

Related

custom UIVIew with nib subviews nil

I create a simple custom UIView with a xib file, I connect xib view to my class, then I linked my IBOutles to subviews, after this I create the view with initWithFrame and I add it programmatically to my parent view
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:#"AddAlarmView" owner:self options:nil];
_scrollView = (UIScrollView *)[objects objectAtIndex:0];
[self addSubview:_scrollView];
}
return self;
}
the problem is that all the subviews are nil....if I try to get customView.textFeild1 it is nil....why?where is the mistake?
Instead of this you should try to get your UIView object from Xib like this..
- (id)initWithFrame:(CGRect)frame
{
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:#"AddAlarmView" owner:self options:nil];
self = (YourClassName *)[objects objectAtIndex:0];
self.frame = frame;
return self;
}
You don't need to add subViews again your IBOutLets. They are already subView of your View in xib file.
Simply load that xib file and assign it to your self and update your frame according to the parameter.

IBOutlets are nil on a XIB view

I have a UIView subclass and it's corresponding XIB. I use this UIView in a UITableViewCell designed in Interface Builder. When dequeuing the cells, I have a correct reference from the cell to the custom view but the IBOutlets of the custom view are nil.
Here is a sample project that shows the problem
https://github.com/JanC/TestXIB
What am I doing wrong?
cheers,
Jan
I don't think it exactly works that way with UITableViewCell, defining it as IBOutlet won't load all the subviews so you have to load it from the bundle using [NSBundle mainBundle] loadNibNamed:#"" owner:self]; and assigned that to your item view
Now it's loading correctly. In the xib, I set the file owner to TAItemTitleView and the Class to just a UIView. I then load the xib in the TAItemTitleView itself
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
NSString *className = NSStringFromClass([self class]);
self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];
[self addSubview:self.view];
}
return self;
}
https://github.com/JanC/TestXIB/blob/master/TestXIB/Classes/Views/TAItemTitleView.m

add subview is not displaying my uiview

I have the following code, and the uiview is not showing, i've placed a breakpoint & see the view is not nil and the frame is set to the given size - why the view is not showing in my uiviewcontroller?
#property (nonatomic,strong) LoadingView *loadingView;
self.loadingView = [[[NSBundle mainBundle] loadNibNamed:#"LoadingView" owner:self options:nil] objectAtIndex:0];
self.loadingView.frame = CGRectMake(110,170,100,100);
[self.view addSubview:self.loadingView];
Your code is logically wrong. Your LoadingView class must allocate before you assigning nib member to it.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:#"LoadingView" owner:self options:nil];
self = [nibs objectAtIndex:0];
}
return self;
}
Your nib assignment should be in the initwithframe method of LoadingView class.
Then Your implementation of adding view would be like,
self.loadingView = [[LoadingView alloc] initWithFrame:CGRectMake(110,170,100,100)];
[self.view addSubview:self.loadingView];

Annotations and Table Views

I am trying populate my table view using my array of annotations but XCode seems to give me a breakpoint any time I add this code.
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSMutableArray *annotations = [[NSMutableArray alloc] init];
if(indexPath.section == 0)
{
for(Location *annotation in [(MKMapView *)self annotations])
{
if(![annotation isKindOfClass:[MKUserLocation class]])
{
}
}
cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
}
return cell;
My annotations:
CLLocationCoordinate2D thecoordinate59;
thecoordinate59.latitude = 51.520504;
thecoordinate59.longitude = -0.106725;
Location *ann1 = [[Location alloc] init];
ann1.title =#"Antwerp";
ann1.coordinate = thecoordinate1;
NSMutableArray *annotations = [NSMutableArray arraywithObjects: ann.. ann59, nil];
[map addAnnotations:annotations];
In cellForRowAtIndexPath, you are declaring a new, local variable named annotations which has nothing to do with the annotations array you are creating in viewDidLoad (I assume that's where you're adding the annotations).
Then in cellForRowAtIndexPath, this line:
for(Location *annotation in [(MKMapView *)self annotations])
fails because there is no annotations property in self. In viewDidLoad, you declared a local variable named annotations but it is not visible or accessible outside that method.
The other issue with the above line is that you're casting self as an MKMapView *. Most likely self is a UIViewController. It contains a map view but is not itself one.
You need to first declare your annotations array at the detail view's class level so it's available across all methods. In the detail view .h file:
#property (nonatomic, retain) NSMutableArray *annotations;
By the way, I'd name it something different so it's not confused with the map view's own annotations property.
In the .m, synthesize it:
#synthesize annotations;
In viewDidLoad, create it like this:
self.annotations = [NSMutableArray arraywithObjects...
[map addAnnotations:self.annotations];
In the numberOfRowsInSection method, return the array's count:
return self.annotations.count;
Then in cellForRowAtIndexPath:
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.section == 0)
{
cell.textLabel.text = [[self.annotations objectAtIndex:indexPath.row] title];
}
return cell;
You are reporting a crash (i assume) on that line
the problem that I see is crash reason would be
cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
annotations array is just initialized locally few statements above which does not hold any values..??

Define a Class instance and create its objects and cast with it [duplicate]

I have the following code:
+ (UITableViewCell *) createTableViewCell: (NSString *) cell_id withTableView: tableView {
SomeViewClass *cell = (SomeViewClass *)[tableView dequeueReusableCellWithIdentifier: cell_id];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed: #"AViewCell"
owner: nil
options: nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass: [UITableViewCell class]]) {
cell = (SomeViewClass *) currentObject;
break;
}
}
}
return cell;
}
I'd like to abstract that code so that it can be used with any view class, not just a "SomeViewClass". I'd like to transform it into something like the following. Notice the cast of the dynamic type (a class *) below.
+ (UITableViewCell *) createTableViewCell: (NSString *) cell_id withTableView: tableView withClass: (Class) a_class {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cell_id];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed: #"AViewCell"
owner: nil
options: nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass: [UITableViewCell class]]) {
cell = (a_class *) currentObject;
break;
}
}
}
return cell;
}
That raises a compile time error. Do I have to resort to macros? Is there a better way to do this?
What if you just cast it to UITableViewCell?
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass: [UITableViewCell class]]) {
cell = (UITableViewCell *) currentObject;
break;
}
}
That shouldn't cause any error (compile or run-time) as long as a_class inherits UITableViewCell.
There is no point whatsoever in what you're trying to do, even if it were possible. That cast does not change the object, for two reasons:
cell is just an argument to the method. Reassigning cell to point to something else merely makes the argument point to a different object; it doesn't cause anything else in the program to change. In particular, other references to the object that cell originally pointed to will continue to point to that original object, blissfully unaware that the method reassigned its argument.
Casting a variable from ClassA * to ClassB * does not magically make the underlying data become a instance of ClassB — it just lies to the compiler about what kind of object the variable is pointing to. The object's class is an attribute of the object itself — that's why the id type is possible.