I am a new Programmer of Iphone..... i have a little problem in accessing the NSMuttable array in my programe...
i am generating a view programmatically on button click .... code on button click is
-(IBAction)buttonClicked
{
secondView=[[TabBarSearchSecondView alloc]init];
[myView addSubview:secondView.view];
}
inTabBarSearchSecondView .h file.....
#interface ......
NSMuttableArray *searchResult;
#end
#property (nonatomic,retain)NSMuttableArray *searchResult;
in TabBarSearchSecondView .m file.........
#synthesize searchResult;
- (void)loadView
{
CGRect cgRct = CGRectMake(0.0, 0.0, 480, 320); //define size and position of view
myView = [[UIView alloc] initWithFrame:cgRct]; //initilize the view
//open database
DbOpenAndClose *dbObject=[[DbOpenAndClose alloc]init];
[dbObject openDatabase];
//for call of search showroom
SearchProduct *object=[[SearchProduct alloc]init];
searchResult=[object searchShowrooms:productname:cityname];
[dbObject closeDatabase];
count=[searchResult count];/// print 3 because 3 record match in database
UITableView *table=[[UITableView alloc]initWithFrame:CGRectMake(4,80,312,325) style:UITableViewStylePlain];
//table.delegate=self;
table.dataSource=self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//NSLog(#"%i", [searchResult count]);
return [searchResult count]; ///Not accessible here...Application Crash Here...
}
thanks for giving your valueable time for my Code...... thanks in Advance
you have to retain the searchResult array....
after this code
searchResult=[object searchShowrooms:productname:cityname];
retain the searchResult. otherwise it is released.. retain the searchResult like this.
[searchResult retain];
Related
I am having a strange issue with TableView. Here is some code to clarify everything:
I am using tabbed panes and this right here is just one of my two ViewControllers:
As you can see, all I do is setting up an UIView and placing a tableView right ontop of it.
#import "SuchenCtrl.h"
#interface SuchenCtrl ()
#end
#implementation SuchenCtrl
#synthesize MainView;
#synthesize Standort;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view = self.MainView;
[self.Standort.tableView setDelegate:self.Standort];
[self.Standort.tableView setDataSource:self.Standort];
[self.MainView addSubview:self.Standort.tableView];
}
- (id)init {
self = [super init];
if(self) {
CGRect rect = [[UIScreen mainScreen] applicationFrame];
self.MainView = [[UIView alloc] initWithFrame:rect];
[self.MainView setBackgroundColor:[UIColor blackColor]];
//Alloc UITableViewController
self.Standort = [[UIStandort alloc] initWithStyle:UITableViewStylePlain];
[self.Standort release];
[self.MainView release];
}
return self;
}
#end
Now UIStandort is another class that simply inherits from UITableViewController. It implements all necessary functions to display data. All im trying to achieve is having the table display "Test" a couple of times but it wont. The table gets displayed nicely but just with empty cells. When I breakpoint one of the implemented functions in the class UIStandort nothing gets called, so my assumption is that the delegate and sourceData are pointing to wrong classes? Though, I explicitly assign those before putting the table on the view.
UIStandort* Standort is declared with properties retain and nonatomic if this helps.
#import "UIStandort.h"
#interface UIStandort ()
#end
#implementation UIStandort
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath(NSIndexPath *)indexPath
{
UITableViewCell* cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.textLabel.text = #"Test";
[cell autorelease];
return cell;
}
#end
Thanks.
You return 0 for the number of row in section. The documentation states:
The number of sections in tableView. The default value is 1.
Can you try:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
I am adding two UITableViews to my view in my code. I am properly setting the delegates and datasource to self. I have added all the delegate methods for returning the number of row, height for row, number of sections etc. And everything is working fine. I have also added index bars to both tables. Now the problem is the index bar is not working for the 1st table, while it is working fine for the second table.
When I click on any character on 1st tables index bar, it responds for the 2nd table. I am not able to get the action for the 1st Table. I also noticed that if I don't add the second table to my view, then I am able to get the action for the 1st table.
Here is my code
- (void)viewDidLoad
{
accountsTable = [[UITableView alloc] initWithFrame:CGRectMake(0,27, 320, 390) style:UITableViewStylePlain];
[accountsTable setDelegate:self];
[accountsTable setDataSource:self];
[self.view addSubview:accountsTable];
accountsTable.backgroundColor = [UIColor clearColor];
[accountsTable release];
keyConnectionsTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 27, 320, 390) style:UITableViewStylePlain];
[keyConnectionsTable setDelegate:self];
[keyConnectionsTable setDataSource:self];
[keyConnectionsTable setBackgroundColor:[UIColor clearColor]];
[keyConnectionsTable setHidden:YES];
[self.view addSubview:keyConnectionsTable];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [NSArray arrayWithArray:[[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
You need to differentiate both table views. To do this you could simply use the "tag" property and set it to different values, or you could have a #property in your view controller for each TableView.
#property (strong) IBOutlet UITableView *tv1;
#property (strong) IBOutlet UITableView *tv2;
For your methods, you could do something like:
- (NSInteger)numberOfSectionsInTableView:(UITableView *) tableView {
if (tableView == self.tv1) {
return 1;
} else if (tableView == self.tv2) {
return 2;
}
}
Bottom Line
You need to differentiate both TableViews or you're going to make a mess :)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Horizontal scrolling UITableView
Can I have a UITableView scrolling horizontally in the iPhone landscape mode ?
This is how it looks like now: http://cl.ly/95xZ
This is how it should be: http://cl.ly/93IY
I was wondering if I should use a UIScrollView for the landscape mode and therefore to switch between UITableView and UIScrollView depending on the orientation of the device...
thanks
You can try this
HorizontalTable for iOS
What you need is UIScrollView with pagination. It works essentially the same way a standard UITable does. When you scroll from left to right you just push new "cells" on the stack and present them.
Here is a sample code:
// .h File
#interface PagingViewController : UIViewController <UIScrollViewDelegate>{
NSMutableArray *cells;
}
#property(nonatomic,retain)NSMutableArray *cells;
-(id)initWithCells:(NSMutableArray*)tableCells;
-(void)loadPage:(int)page;
#end
// .m File
#interface PagingViewController ()
#property(nonatomic,retain)NSMutableArray *viewControllers;
#property(nonatomic,retain)UIView *contentView;
#property(nonatomic,readwrite)NSUInteger numberOfPages;
#end
#implementation PagingViewController
#synthesize viewControllers;
#synthesize contentView;
#synthesize cells;
#synthesize numberOfPages;
-(id)initWithCells:(NSMutableArray*)tableCells{
self = [super init];
if(self) {
self.cells = tableCells;
numberOfPages = [cells count];
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < numberOfPages; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = contentView;
[self loadPage:0];
}
return self;
}
- (void)loadPage:(int)page{
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
else if(page > 0){
CustomCellVC *cell = [viewControllers objectAtIndex:page];
if ((NSNull *)cell == [NSNull null]){
cell = (CustomCellVC*)[cells objectAtIndex:page];
[viewControllers replaceObjectAtIndex:page withObject:cell;
[cell release];
}
if (cell.view.superview == nil)
{
[contentView addSubview:cell.view];
}
}
}
//Dont forget to dealloc.
I wrote this from memory so there might be little bugz.
To implement horizontal scrolling you should use UIScrollView and manage its subviews manually. It's not very hard as it sounds. There are several videos from WWDC about technics which you can use to work with scroll view. They are worth watching.
Advanced ScrollView Techniques at
https://developer.apple.com/videos/play/wwdc2011/104/
Designing Apps with Scroll Views at
https://developer.apple.com/videos/play/wwdc2010/104/
Very simple example, how to show scrollView when user rotates device to landscape:
//header
// tableView and scrollView has the same superview
// scrollView is placed above tableView
#property(nonatomic, retain) IBOutlet UITableView *tableView;
#property(nonatomic, retain) IBOutlet UIScrollView *scrollView;
//implementation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[UIView animateWithDuration:duration
animations:^(void) {
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
self.scrollView.alpha = 1.0f;
} else {
self.scrollView.alpha = 0.0f;
}
}];
}
I would put the UITableView inside the UIScrollView. This gives you the horizontal scrolling.
But I'm a litte bit confused: The 2nd screenshot shows a UINavigationController?
I have a UITabBarController with three ViewControllers (A, B, and C). In ViewControllerB I have a UIScrollView. The UIScrollView consists of several instances of my PhotoViewController. These PhotoViewController objects are called from ViewControllerA, not ViewController B, where they're located.
The PhotoViewController instances have a UIImage and a two buttons. And at first, when I clicked on a button in one of my PhotoViewController instances I received a 'Thread 1: Program received signal: "EXC_BAD_ACCESS"' error. Looking around on stackoverflow that error seems to appear whenever there are memory management issues.
Since I was creating the PhotoViewController objects in a loop from a method called in ViewControllerA, and releasing those objects, I figured that by the time I switched over to ViewControllerB they were already released - and hence the memory issue.
But that's just my guess. Could you tell me if I should just stop releasing the PhotoViewController objects inside of the loop code? Because that's what I did (just commented that line out) and the program "works" fine. However, I'm still not sure if this is the proper way to handle it and if it is causing unknown memory management issues.
Here is some of my code:
ViewControllerA.m
//Creating an album in ViewControllerB, the photos in the album are PhotoViewController objects
-(IBAction)showAlbum:(UIButton *)sender
{
//Go goes here to get an album and display it in the UIScrollView
albumID = #"ALBUM_ID";
NSString* graphUrl = [NSString stringWithFormat:#"%#/photos?limit=10", albumID];
[_facebook requestWithGraphPath:graphUrl andDelegate:self];
}
...
- (void)request:(FBRequest *)request didLoad:(id)result {
//Code for array of photos
NSLog(#"%#",result);
NSString *requestType = [request.url stringByReplacingOccurrencesOfString:#"https://graph.facebook.com/" withString:#""];
if ([requestType isEqualToString:[NSString stringWithFormat:#"%#/photos?limit=10", albumID]]){
NSArray *photoAlbumArray=(NSArray*)[result valueForKey:#"data"];
[self.label setText:[NSString stringWithFormat:#"%i", [photoAlbumArray count]]];
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[ViewControllerB class]])
{
ViewControllerB *mtbvc = (ViewControllerB *)controller;
[mtbvc setArray:photoAlbumArray];
self.tabBarController.selectedIndex = 1;//switch over to the second view to see if it worked
}
}
}
...
#end
ViewControllerB.m
//loop where I create PhotoViewController objects
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
arrayCount = [array count];
scroller.delegate=self;
scroller.pagingEnabled=YES;
scroller.directionalLockEnabled=YES;
scroller.showsHorizontalScrollIndicator=NO;
scroller.showsVerticalScrollIndicator=NO;
//should have an array of photo objects and the number of objects, correct?
scrollWidth = 0;
scroller.contentSize=CGSizeMake(arrayCount*scroller.frame.size.width, scroller.frame.size.height);
for (int i = 0; i < arrayCount;i++) {
PhotoViewController *pvc = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
UIImageView *scrollImageView = [[UIImageView alloc] initWithFrame:CGRectOffset(scroller.bounds, scrollWidth, 0)];
CGRect rect = scrollImageView.frame;
pvc.view.frame = rect;
[pvc view];
pvc.label.textColor = [UIColor whiteColor];
id individualPhoto = [array objectAtIndex:i];
NSLog(#"%#",individualPhoto);
NSArray *keys=[individualPhoto allKeys];
NSLog(#"%#",keys);
NSString *imageURL=[individualPhoto objectForKey:#"source"];
//here you can use this imageURL to get image-data and display it in imageView
NSURL *url = [NSURL URLWithString:imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
pvc.imageView.image = [[UIImage alloc] initWithData:data];
pvc.label.text = [individualPhoto objectForKey:#"id"];
//check to make sure the proper URL was passed
//I have an imageView next to the UIScrollView to test whether that works - it does.
[scroller addSubview:pvc.view];
[scrollImageView release];
//[pvc release];
scrollWidth += scroller.frame.size.width;
}
if (arrayCount > 3) {
pageControl.numberOfPages=3;
} else {
pageControl.numberOfPages=arrayCount;
}
pageControl.currentPage=0;
//[self.view addSubview:scroller];
}
PhotoViewController.m
#import "PhotoViewController.h"
#implementation PhotoViewController
#synthesize label, imageView;
-(IBAction)likeButton:(UIButton *)sender
{
//code goes here
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[DemoAppViewController class]])
{
DemoAppViewController *davc = (DemoAppViewController *)controller;
[davc likePicture:self.label.text];
}
}
self.tabBarController.selectedIndex = 0;//switch over to the third view to see if it worked
}
-(IBAction)skipButton:(UIButton *)sender
{
//code goes here
}
-(IBAction)likeCommentButton:(UIButton *)sender
{
//code goes here
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (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 YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
PhotoViewController.h
#import <UIKit/UIKit.h>
#import "DemoAppViewController.h"
#import "MyTabBarViewController.h"
#interface PhotoViewController : UIViewController {
IBOutlet UILabel *label;
IBOutlet UIImageView *imageView;
UIButton *likeButton;
UIButton *skipButton;
UIButton *likeCommentButton;
}
#property (nonatomic, retain) UILabel *label;
#property (nonatomic, retain) UIImageView *imageView;
-(IBAction)likeButton:(UIButton *)sender;
-(IBAction)skipButton:(UIButton *)sender;
-(IBAction)likeCommentButton:(UIButton *)sender;
#end
To write iOS apps, it is critical that you understand the memory management rules.
In ViewControllerB, viewDidLoad, you alloc the pvc.
Further down, you add the pvc's view as a subview of the scroller. This retains the pvc's view, but not the pvc itself. Then when you release the pvc, it's retain count is zero, and when you reference it later, it's gone. Crash. It seems like you need to pass in and retain a reference to the pvc in the controller that's using it.
I am not sure why you are using PhotoViewController(Subclassing UIViewController) instead of PhotoView(subclassing UIView). As you are not using any of the facility of the viewcontroller(no life cycle method and other).
If you subclass PhotoViewController with UIView and remove the viewcontroller's methods it will work and will not cause any memory issues as you have aleready discussed in your discussion with Rayfleck. ( it will be retained by parent view controller.)
If you are thinking about the events, then these will also be handled by view itself. But if you want to handle it in your controller then you can easily delegate, or pass your controller reference and invoke the event on it.
Thanks,
I am using DTGridView from the DTKit by Daniel Tull. I implemented it in a very simple ViewController and the test I am doing is to place a button in the last row of the grid, which should add another row to the grid (and therefor moving the button to a row beneath it).
The problem is, when I click the button a couple of times and then start scrolling, the grid seems to lose its content. As I am not completly sure this is a bug in the grid, but more in my code, I hope you guys can help me out and track down the bug.
First I have my header file, which is quite simple, because this is a test:
#import <UIKit/UIKit.h>
#import "DTGridView.h"
#interface TestController : UIViewController <DTGridViewDelegate, DTGridViewDataSource>
{
DTGridView* thumbGrid;
}
#end
I declare a DTGridView, which will be my grid, where I want to put content in.
Now, my code file:
#import "TestController.h"
#implementation TestController
int rows = 1;
- (NSInteger)numberOfRowsInGridView:(DTGridView *)gridView
{
return rows;
}
- (NSInteger)numberOfColumnsInGridView:(DTGridView *)gridView forRowWithIndex:(NSInteger)index
{
if (index == rows - 1)
return 1;
else
return 3;
}
- (CGFloat)gridView:(DTGridView *)gridView heightForRow:(NSInteger)rowIndex
{
return 57.0f;
}
- (CGFloat)gridView:(DTGridView *)gridView widthForCellAtRow:(NSInteger)rowIndex column:(NSInteger)columnIndex
{
if (rowIndex == rows - 1)
return 320.0f;
else
return 106.6f;
}
- (DTGridViewCell *)gridView:(DTGridView *)gridView viewForRow:(NSInteger)rowIndex column:(NSInteger)columnIndex
{
DTGridViewCell *view = [[gridView dequeueReusableCellWithIdentifier:#"thumbcell"] retain];
if (!view)
view = [[DTGridViewCell alloc] initWithReuseIdentifier:#"thumbcell"];
if (rowIndex == rows - 1)
{
UIButton* btnLoadMoreItem = [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 301, 57)];
[btnLoadMoreItem setTitle:[NSString stringWithFormat:#"Button %d", rowIndex] forState:UIControlStateNormal];
[btnLoadMoreItem.titleLabel setFont:[UIFont boldSystemFontOfSize:20]];
[btnLoadMoreItem setBackgroundImage:[[UIImage imageNamed:#"big-green-button.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
[btnLoadMoreItem addTarget:self action:#selector(selectLoadMoreItems:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:btnLoadMoreItem];
[btnLoadMoreItem release];
}
else {
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(10,0,100,57)];
label.text = [NSString stringWithFormat:#"%d x %d", rowIndex, columnIndex];
[view addSubview:label];
[label release];
}
return [view autorelease];
}
- (void) selectLoadMoreItems:(id) sender
{
rows++;
[thumbGrid setNeedsDisplay];
}
- (void)viewDidLoad
{
[super viewDidLoad];
thumbGrid = [[DTGridView alloc] initWithFrame:CGRectMake(0,0, 320, 320)];
thumbGrid.dataSource = self;
thumbGrid.gridDelegate = self;
[self.view addSubview:thumbGrid];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
I implement all the methods for the DataSource, which seem to work. The grid is filled with as many rows as my int 'rows' ( +1 ) has. The last row does NOT contain 3 columns, but just one. That cell contains a button which (when pressed) adds 1 to the 'rows' integer.
The problem starts, when it starts reusing cells (I am guessing) and content start disappearing. When I scroll back up, the UILabels I am putting in the cells are gone.
Is there some bug, code error, mistake, dumb-ass-move I am missing here? Hope anyone can help.
I've had a quick look at the code and you should definitely be calling reloadData instead of setNeedsDisplay in selectLoadMoreItems like so:
- (void) selectLoadMoreItems:(id) sender {
rows++;
[thumbGrid reloadData];
}
Let me know if this fixes it, if not I'll take a proper look through your code later today.
There's a pull request that seems to solve this issue. The bottom line is calling initialiseViews everytime checkViews is called.