UIView subclass dealloc not called - objective-c

I am using AQGridView for displaying a grid of images in my app. A user clicks on an album and then I open a new controller with the grid that has all the images. The problem is that the when the user presses the back button to go back to the list of albums, the dealloc on the grid view is not getting called. I have logged a string in dealloc of my view controller and it is being called.
I have checked the heapshots in Instruments and everything related to AQGridView is not deallocated even after the view is popped. I use Interface Builder to create the grid view and it is connected to grid view in my .h file.
#property (weak, nonatomic) IBOutlet AQGridView *gridView;
I am not holding any other pointers to the grid view. I am using ARC for the project. Do I need to deallocate the gridView somehow in the grid view controller's dealloc or is it handled automatically by ARC? If it is, what might be preventing it from being deallocated?
EDIT:
I am using NSOperationQueue to load the images in the background and then after the images are loaded, I put them in grid cells.

In the dealloc method of your grid view controller, set the gridView pointer to nil.
-(void)dealloc
{
self.gridView = nil;
}

Related

reloadData not triggering cellForRowAtIndexPath

I have a UIViewController with one UITableView in it. The table view holds a list of favorites that can be changed by other parts of the app. I am using NSNotificationCenter to trigger the table view's reloadData method. The table view has an outlet declared as follows:
#property (strong,nonatomic) IBOutlet UITableView *faveTableView;
and synthesized as follows:
#synthesize faveTableView;
The delegate and datasource properties of the table view are set in the view controller's viewDidLoad as follows:
[self.faveTableView setDataSource:self];
[self.faveTableView setDelegate:self];
The NSNotificationCenter causes the following method to fire:
-(void)reloadNotificationReceived{
[self loadData];
[self.faveTableView reloadData];
}
loadData updates the data source which is NSMutableArray of managed objects and is working as it should.
When the view controller loads, cellForRowAtIndexPath is fired as it should be. However, when the notification is received, reloadNotificationReceived is fired and two of the table view delegate methods (numberOfRowsInSection and numberOfSectionsInTableView) ARE fired. However, cellForRowAtIndexPath is NOT fired. numberOfRowsInSection IS returning the correct number of items.
Can anyone offer up a reason why cellForRowAtIndexPath does not get fired here? Thanks!
The number of rows you are returning is 0.
Perhaps you have set the delegate/datasource of the tableview to your controller in the storyboard/xib, but you haven't wired up the "faveTableView" tableview IBOutlet of the the controller... If the del/datasource are set, then the it will successfully get data from the controller, but without the IBOutlet being set, the self.faveTableView will remain nil and hence [self.faveTableView reloadData] won't do anything. Put a breakpoint in your viewDidLoad and check whether the self.faveTableView is not nil...

Add UITableViewController to other View

Is it possible to embed (add as subview) a UITableViewController into another View Controller programmatically? I found a few answers here on StackOverflow but none worked for me with ARC and iOS6 SDK.
I know you can do this easily with Navigation and TabBar controllers but I am more curious about adding tableviews to a regular View controller. I need my tableview to occupy the lower part of the available screen space (I need the rest for other purposes, for which neither tab nor navigation types are suitable).
When I tried to do it, however, it did not work. I instantiated a subclassed UITableViewController, but when I added it to my self.view as a subview, the compiler said I tried to use "incompatible pointer types." Not only that, my instantiated UITableViewController does not have a .frame property, so I cannot set it dimensions, which would be the whole point of this exercise.
Building upon ogres answer, you should add the tableViewController's view as a subview, but it is not everything. The tableViewController is a viewController and it needs to know its parent and its children, to do its viewController-job correctly. I do not know any details here, but there is an entire talk about this from WWDC 2011 called "Implementing UIViewController Containment".
One problem I have experienced when only adding the view as a subview is that target actions don't seem to work. Tapping a UIButton or similar causes either a EXC_BAD_ACCESS or a unrecognized selector sent to instance.
So I recommend that you do something like this:
UIViewController *vc = //Your tableViewController
[self addChildViewController:vc]; //Important
[self.view addSubview:vc.view];
//If you want to set the frame, set the frame of the tableViewController's view
vc.view.frame = ...
yes , you can use tableview in another view without any problems
UITableViewController, but when I added it to my self.view as a subview
are you trying to add viewcontroller as subview or its view ? ( viewcontroller.view )
UITableViewController does not have a .frame property,
of course it does not have .frame property , it is a view CONTROLLER , you should see .view.frame

Obj-c UIImageView is null when calling from outside class

I have a UIViewController containing a UIImageView that has been correctly wired up (I can set image inside controller).
I have also set an iVar using
UIImageView *_imgQRCode;
and a property using
#property (strong, nonatomic) IBOutlet UIImageView *imgQRCode;
Synthesized using:
#synthesize imgQRCode = _imgQRCode;
But when I call something like below I nothing happens the image and when I inspect in Xcode the reference is memory reference is 0x00000000. note the code works when called inside the ViewController. The following is called from any other view controller with controller instantiated as follow:
QRPopupViewController *qrPop = [[QRPopupViewController alloc] initWithNibName:#"QRPopupViewController" bundle:nil];
[controller.imgView setImage:[UIImage imageNamed:#"sample.png"]];
Any ideas how to fix this and why i'm getting null?
Firsty: outlets should be weak
#property (weak, nonatomic) IBOutlet UIImageView *imgQRCode;
You have to hook imgQRCode outlet to your viewController, and you can use it inside viewDidLoad.
You will get null for all UI Control's instances which are not part of the currently visible view controller. So due to this all your calls to that UI control will not perform the UI related operation.
If you want to update any UI control which is not part of currently visible view controller, you can use app delegate. It is the only place which is centralized in between all view controllers.
There is a mechnism, called "protocol delegate" to call some method to update UI part from the currently visible view controller. You can go through this URL for detail about this.
If you are selecting the approach of "protocol delegate", then explore the method execution flow in detail. When you call a protocol from a method of currently visible view controller, the corresponding protocol implementation method will be called after the completion of the caller method. So you need to take care of synchronization.

UITableView on DetailView of SplitView doesn't load it's data

Using Xcode 4.3.1, ipad app for iOS 5.1, no core-data
On my storyboard I have a master-detail project. The master obviously has a TableView, and that works fine: by selecting an item in the master tableview my detail data is set in the detail view controller by the template code call setDetailItem (which I call from 'didSelectRowAtIndexPath'). That works fine.
My DetailView/Scene contains (another) UITableView (amongst other, also some TextFields etc.)
This UITAbleView's datasource and delegate are connected to the detail view controller.
In the detail viewcontroller's interface file I adde the protocols UITableViewDataSource and UITableViewDelegate (next to the pre-configured UISplitViewControllerDelegate).
I implemented the methods numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath, didSelectRowAtIndexPath methods in the detail view controller.
However, these are only called when the master tableview's list is build up, not when I select an item in the master list/tableview. When I select an item in the master list/tableview the detail data get's set in the detail viewcontroller, but for instance the 'cellForRowAtIndexPath' in the detail controller is never called, and the detail TableView is not updated/initialised. (The textfield in the detail view however is loaded with the correct data).
I guess I am missing something. Do I have to give the tableview a kick at the point I prepared it's data? And if so, how...? The tableview itself is not connected to an outlet or action, should it?
Thanks!
You need to implement a custom delegate (one-to-one communication) from RootView to Detailview.
Like the following,
Implement the Delegate in RootView,
#protocol RootViewControllerDelegate <NSObject>
-(void)didchangeSelectionInRootViewList:(id)toItem;
#end
And call the delegate when needed as (in your case on table view didSelectRowAtIndexPath),
//a delegete need in caes of splitview to refresh the detailview.
-(void)callDelegate:(id)sender {
if(self.delegate && [self.delegate respondsToSelector:#selector(didchangeSelectionInRootViewList:)]) {
[self.delegate didchangeSelectionInRootViewList:sender];
}
}
And don't forgot to set the delegate in Rootview as detailview while creating splitview controller.
And also catch the delegate in Detailview and reload the TableView with sufficient data to load.
thanks,
Naveen Shan

Object mixup between programmatically created view and interface builder placeholder

I have a view controller which contains a scroll view. Inside the scroll view there is another UI core graphics view. In the view controller I create a temp object for the core graphics view and assign some data to it, then assign it to the attribute of the view controller. Eg: In the view controller:
#interface controller : UIViewController {
GraphView *graph;
}
#property ... IBOutlet GraphView *graph;
#implementation
GraphView *temp = [[GraphView alloc] init];
temp.someArray = anExistingDataArray;
self.graph = temp;
In IB, I open the view controller nib and add a scroll view, and embed a view and assign it the core graphics view class. Then hook up the IBOutlet from that view to the attribute in the view controller.
My problem is that the view controller creates the temp view object, assigns it to itself, with the correct data, however IB seems to instantiate its own object (different memory ID) and displays that, instead of the one in the view controller.
What is the correct way to build this type of setup?
If you drag an object into a nib, IB creates and archives that object. This is why you don't have to alloc/init views that you create in IB.
I'm guessing that you are creating your view in IB so that you can get the geometry correct, or...? It's rather unusual to create a view and then immediately replace it at run-time. More common, for geometric purposes, is to create a container view in IB and then add your programmatically-created views as subviews of that.
Your code left out the most important piece of this, though, which is when it's getting run. Is it in -init...? -awakeFromNib? -loadView? -viewDidLoad? The exact location matters since these occur in a well-defined sequence. If you put your code in the wrong place, it will run before the nib is unarchived and fully reconnected, so the nib will clobber whatever your code did.
So: when is your [self setGraph] (I can't bring myself to use dot syntax) code getting run?