loading custom view using loadNibNamed showing memory leaks - iphone

I have a number of custom table cells and views that I built using interface builder
In interface builder, everything is set up similarly. There is a table cell and a couple other UILabels and a background image
Object owner if the nib is NSObject
Class for the table cell is the name of the class for my table cell
Here is how I create the table cell in my code:
SectionedSwitchTableCell *cell = nil;
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:kSectionedSwitchTableCellIdentifier owner:owner options:nil];
for(id currentObject in nibs)
{
if([currentObject isKindOfClass:[SectionedSwitchTableCell class]])
{
cell = (SectionedSwitchTableCell *)currentObject;
break;
}
}
return cell;
For my custom table headers I have this
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:#"CustomTableHeader" owner:self options:nil];
for(id currentObject in nibs)
{
if([currentObject isKindOfClass:[CustomTableHeader class]])
{
return header
}
}
In my .h and .m files for the custom view, I have IBOutlet, #property set up for everything except for the background image UIImageView. Everything that has the IBOutlet and #property are also #synthesized and released in the .m file.
Leaks is showing that I have memory leaks with CALayer when I create these custom view objects. Am I doing something wrong here when I create these custom view objects? I'm kind of tearing my hair out trying to figure out where these leaks are coming from.
As a side note, I have a UIImageView background image defined in these custom views but I didn't define properties and IBOutlets in my .h and .m files. Defining them doesn't make a difference when I run it through Leaks but just wanted to confirm if I'm doing the right thing.
Any input would be super helpful. Thanks :)

Check your custom cell xib file, ensure you have set the identifier (kSectionedSwitchTableCellIdentifier) to the cell.
I have the similar problem and fixed with this.

Related

creating a reusable control

(Using IOS 6, XCode 4.6, ARC, Storyboard)
I'm Trying to create a reusable UIView (like user control in C#), because I have two viewControllers having the same data one for input and other for display.
I read here that the way to do it is by creating a separate xib file for the ReusableUIView, as well as creating corresponding h + m files for it. Adding all the controls and linking the outlets to them.
In the storyboard I have UIViewController, in its viewDidLoad i wrote the following code:
NSArray *myNibsArray = [[NSBundle mainBundle] loadNibNamed:#"ReusableUIView" owner:self options:nil];
ReusableUIView *myCustomView = [myNibsArray objectAtIndex:0];
Few questions:
nothing happens at this point so I'm guessing i have to connect somehow self (the UIViewController) with myCustomView
The ReusableUIView is one of many controls in the UIViewController how do i set it's place
In the xib file i can't find a way to set the size of the UIView, where and when we set the size of it
It is better to custom view loading it its class itself - add some static method in your custom view class that will look like this:
'+' (ReusableUIView *) loadView {
ReusableUIView *loadedView = nil;
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:#"ReusableUIView"
owner:self options:nil];
if ([nibs count] > 0) {
loadedView = [myNibsArray objectAtIndex:0];
}
return loadedView;
}
As ReusableUIView inherits UIView you can easily config its sizes and positions using frame property and adding it as a subview on parent view.
I am not sure what is the problem, but you can change view sizes in xib easily.
Also, please note two things:
When you are loading view from nib then - (id) initWithCoder(NSCoder *)aDecoder constructor method is calles. So if you need any additional setups - you have to implement then in this method.
When you are making custom view with xib and .h/.m files you have to mark you custom class in xib not on files owner but directly on your UIView.

Custom UITableCellVew when there is a referencing outlet wired up in IB

I am trying to use custom UITableViewCells defined in IB where there are referencing outlets. I have successfully used the techniques shown in several places in stackoverflow to load and use UITableViewClass when there is no referencing outlet, like below.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TheCellsClass" owner:nil options:nil];
I have a separate file called "TheCellsClass.xib", which has a single UITableViewCell defined with a single UILable called Alabel, "IBOutlet UILabel *Alabel;". If I connect the label to ALabel then I get this error
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x681b360> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Alabel.'
After searching here and the web I understand that this is caused by the fact that "owner:nil" does not define a class with this object:Alabel. I cannot use "owner:self" because that is the UITableViewController, and also does not define "Alabel".
I created a class called "TheCellsClass" as a sub class of "UITableViewCell" that does define Alabel, see below;
Then used:
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TheCellsClass" owner:cell options:nil];
I still get the same error. So, can anyone point out the error of my ways? :-)
I only way I can think to fix this is to remove all referencing outlets and connect
them using code
Subclass header :
#import <UIKit/UIKit.h>
#interface TheCellsClass : UITableViewCell {
IBOutlet UILabel *Alabel;
}
#property (strong, nonatomic) UILabel *Alabel;
#end
Subclass body:
#import "TheCellsClass.h"
#implementation TheCellsClass
#synthesize Alabel;
#end
In the table view controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I am using:
TheCellsClass* cell= [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TheCellsClass" owner:cell options:nil];
A zip of a sample project is here http://www.proaa.com/tryout.zip
Suggestions? Requests for more info?
Any help appreciated.
Geoff
Three things:
Remove TheCellClass from DetailViewController.xib
ALabel is linked to File's Owner in TheCellsClass - link it instead to TheCellsClass in the Objects section. Also consider renaming ALabel - it is standard to name instance variables beginning with a lowercase letter.
In MasterViewController, change
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TheCellsClass" owner:cell options:nil];
to
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TheCellsClass" owner:nil options:nil];
After these three changes, your custom TableViewCell appeared in the simulator. Also consider renaming TheCellsClass to something that hints at what it's subclassing, like MyCustomTableViewCell.
Without looking at your project, one thing comes to mind. If you have an instance of your custom cell in our nib, and then you have this label in that same nib, then the connection should be from the UILabel to the custom cell. You shouldn't be connecting it to file's owner, at least from the way you've described what you're trying to achieve.
Hope that helps.

loadNibNamed loaded but class is ignored !

NIB file is loaded successfully in my scrollView but sounds like it's class is totally ignored as if the xib is not associated with it, i checked that by accessing the class direct and its working fine showing all the NSLogs in viewDidLoad and UILable.text = # ...etc.,
But after loading the same xib i can't see but a dead interface
Asking after a whole day of searching on this issue. Thanks in advance for you super guys
Loading Nib by: ( in Setting.m )
NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:#"SettingProfile" owner:self options:nil];
UIView *settingA = [nibViews objectAtIndex: 0];
[ScrollView addSubview:settingA];
SettingProfile.h
#class SettingProfile;
#interface Setting UIViewController {
SettingProfile *SettingProfile;
}
#property (nonatomic, retain) SettingProfile *settingProfile;
It looks like you are loading the Nib into a UIView which may not be the result you are looking for... I use the nib loading in my Table View... Perhaps this snippet will help you
OfferCell *cell = nil;
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"OfferCell" owner:self options:nil];
cell = (OfferCell*)[nib objectAtIndex:0];
I then do whatever I want with by cell.
Including add it to the tableView...
When I retrieve it I cast it into the OfferCell object again.
Partially solved, to those whom facing the same problem just add the loaded Nib name in the owner:
NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:#"SettingProfile" owner:#"SettingProfile" options:nil];
UIView *gridView = [nibViews objectAtIndex: 0];
[ScrollView addSubview:gridView];
Still trying to connect the outlets in the loaded Nib/class correctly, i know connecting it with the same file owner is wrong causing app crash.

How to use a xib and a UIView subclass together?

I'd like to create a couple of custom views, sort of reusable UI components, and would prefer to not layout the UI in code in the UIView subclass. I'd like to use a xib for that. I've used a xib by itself. And I've used a UIView subclass by iteself. But I haven't used them together. How do I "attach" them to one another? I'd like to use IBOutlets to access the UILabels in my custom view.
Will this kind of thing work?
NSArray *xib = [[NSBundle mainBundle] loadNibNamed:#"MyCustomView" owner:self options:nil];
MyCustomView *view = [xib objectAtIndex:0];
view.myLabel.text = #"fred";
Yes that's the way that it works when you're loading xibs that aren't parents to viewControllers
Edit August 15, 2013:
You can't always just assume that you're going to get exactly what you're looking for out of index 0 of the returned NSArray, which is what makes it good to use type checking.
NSArray *xibArray = [[NSBundle mainBundle] loadNibNamed:#"MyCustomView" owner:nil options:nil];
MyCustomView *myView = nil;
for (id xibObject in xibArray) {
//Loop through array, check for the object we're interested in.
if ([xibObject isKindOfClass:[MyCustomView class]]) {
//Use casting to cast (id) to (MyCustomView *)
myView = (MyCustomView *)xibObject;
}
}

Detecting when a cell's detail-disclosure button has been clicked (when using a custom cell XIB)

if (cell == nil) // 1
{ // 2
[[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil]; // 3
cell = tvCell; // 4
self.tvCell = nil; // 5
} // 6
There's some code from an Apple example of using your own "custom cell XIB" to create cells in a UITableView.
It appears to work... but I think I would do better to actually understand what is being done there.
Why isn't the following assigning the value to something?
cell = [[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil];
(In fact, cell and tvCell aren't being used at all.)
Why is line #4 assigning using tvCell when nothing has been put it in at all, yet?
Why is line #5 nulling out the tvCell that I need?
Why is this line using assign, not retain?
#property (nonatomic, assign) IBOutlet UITableViewCell *tvCell;
About the only thing I can't get working correctly is when I put a disclosure-button on my custom cell XIB. Is there a way for me to detect when the user has clicked on it? (Hopefully, without using 100s of TAGs.)
I haven't played with XIBs for cells, but I don't see why you couldn't still use tableView:accessoryButtonTappedForRowWithIndexPath:.