I'm am working on using BLE on a project previously using MFi devices.
The goal is to achieve a sort of serial connection.
With EAaccessory I had a popover asking for the device to connect to and was working fine.
Using CB, I added a view that I call to scan and select the device to connect to.
I can connect the device fine, but when I go back to main view, I loose the connection to the peripheral.
CoreBluetooth[WARNING] <CBConcretePeripheral: ... IsConnected = YES> is being dealloc'ed while connected
So, as I am not a genius nor a good iOs programmer...
Could someone point me in the right direction to retain the connected peripheral from one view to the main ?
I tried to understand a sample from ConnectBlue, the manufacturer of the BT devices on my project, but they use Storyboard, and I don't.
Using their demo, I can connect to the peripheral, on the main view and chat with it on another view.
I tried to google, but found nothing relevant.
Edit:
The connection code part
#import "ScanTableViewController.h"
#import <CoreBluetooth/CBCentralManager.h>
#import <CoreBluetooth/CBPeripheral.h>
#import "DiscoveredPeripheral.h"
#import "ScanCell.h"
typedef enum
{
SCAN_S_NOT_LOADED,
SCAN_S_DISAPPEARED,
SCAN_S_WILL_DISAPPEAR,
SCAN_S_APPEARED_IDLE,
SCAN_S_APPEARED_SCANNING
} SCAN_State;
#interface ScanTableViewController ()
#end
#implementation ScanTableViewController
{
SCAN_State state;
CBCentralManager *cbCentralManager;
NSMutableArray *discoveredPeripherals;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Scan viewDidLoad");
cbCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
// Do any additional setup after loading the view from its nib.
CGRect tableViewFrame = self.view.bounds;
UITableView *tableview = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStylePlain];
self.myTableView = tableview;
self.myTableView.rowHeight = 60;
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
//Make sure our table view resizes correctly
self.myTableView.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
[self.view addSubview:tableview];
discoveredPeripherals = [[NSMutableArray alloc] init];
//[cbCentralManager retrieveConnectedPeripherals];
state = SCAN_S_DISAPPEARED;
}
- (void)viewDidUnload
{
//[self setScanButton:nil];
[super viewDidUnload];
NSLog(#"Scan viewDidUnload");
cbCentralManager = nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
state = SCAN_S_NOT_LOADED;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"Scan viewWillAppear");
[self.myTableView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"Scan viewDidAppear");
[self clearPeriph];
state = SCAN_S_APPEARED_IDLE;
[self.myTableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
NSLog(#"Scan viewWillDisappear");
//[self scan: FALSE];
state = SCAN_S_WILL_DISAPPEAR;
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(#"Scan viewDidDisappear");
state = SCAN_S_DISAPPEARED;
}
-(void) enterForeground
{
NSLog(#"Scan enterForeground");
[self clearPeriph];
state = SCAN_S_APPEARED_IDLE;
}
-(void) enterBackground
{
NSLog(#"Scan enterBackground");
[self scan: FALSE];
state = SCAN_S_DISAPPEARED;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) initWithPeripherals: (NSMutableArray*) dp
{
NSLog(#"Scan initWithPeripherals");
discoveredPeripherals = dp;
state = SCAN_S_NOT_LOADED;
}
#pragma mark - Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//NSLog(#"Nombre de sections");
return 2;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSInteger nRows;
switch(section)
{
case 0:
nRows = 1;
break;
case 1:
NSLog(#"Scan Nbre ligne section 1 : %i",discoveredPeripherals.count);
nRows = discoveredPeripherals.count;
break;
default:
nRows = 0;
break;
}
return nRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(#"Remplissage");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
}
NSLog(#"Scan Section table:%u",indexPath.section);
switch(indexPath.section)
{
case 0:
{
cell.textLabel.text = #"";
if(state == SCAN_S_APPEARED_SCANNING)
{
cell.textLabel.text = #"Stop Scan";
//cell.labelInfo.text = #"Active";
//[cell.activityView startAnimating];
}
else
{
cell.textLabel.text = #"Start Scan";
//cell.labelInfo.text = #"Inactive";
//
//[cell.activityView stopAnimating];
}
break;
}
case 1:
{
if ( [discoveredPeripherals count] > 0)
{
DiscoveredPeripheral* discoveredPeripheral;
discoveredPeripheral = [discoveredPeripherals objectAtIndex:indexPath.row];
cell.textLabel.text =discoveredPeripheral.peripheral.name;
}
cell.detailTextLabel.textColor = [UIColor blackColor];
}
}
return cell;
}
- (NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *str;
switch(section)
{
case 0:
str = #"Bluetooth Low Energy Scanning";
break;
case 1:
str = #"Found Devices";
break;
default:
break;
}
return str;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(cbCentralManager.state == CBCentralManagerStatePoweredOn)
{
//ScanCell* cell = (ScanCell*)[tableView cellForRowAtIndexPath:indexPath];
//static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(indexPath.section == 0)
{
if(state == SCAN_S_APPEARED_SCANNING)
{
[self scan: FALSE];
cell.textLabel.text = #"Start Scan";
//cell.labelInfo.text = #"Inactive";
//[cell.activityView stopAnimating];
state = SCAN_S_APPEARED_IDLE;
}
else if((state == SCAN_S_APPEARED_IDLE) &&
(cbCentralManager.state == CBCentralManagerStatePoweredOn))
{
[self scan: TRUE];
cell.textLabel.text = #"Stop Scan";
//cell.labelInfo.text = #"Active";
//[cell.activityView startAnimating];
state = SCAN_S_APPEARED_SCANNING;
}
}
else
{
DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:indexPath.row];
NSDictionary *dictionary;
switch (dp.state)
{
case DP_STATE_IDLE:
cell.textLabel.text = #"Connecting";
//[cell.activityView startAnimating];
dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];
[cbCentralManager connectPeripheral:dp.peripheral options:dictionary];
dp.state = DP_STATE_CONNECTING;
break;
case DP_STATE_CONNECTED:
case DP_STATE_CONNECTING:
[cbCentralManager cancelPeripheralConnection:dp.peripheral];
cell.textLabel.text = #"";
//[cell.activityView stopAnimating];
cell.accessoryType = UITableViewCellAccessoryNone;
dp.state = DP_STATE_IDLE;
break;
default:
break;
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
- (void) scan: (bool) enable
{
if(enable == TRUE)
{
NSLog(#"Scan Scan ON");
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
[cbCentralManager scanForPeripheralsWithServices:nil options:dictionary];
}
else
{
NSLog(#"Scan Scan Off");
[cbCentralManager stopScan];
}
}
- (IBAction)startScan:(id)sender {
if(state == SCAN_S_APPEARED_IDLE)
{
[self scan: TRUE];
state = SCAN_S_APPEARED_SCANNING;
}
else if(state == SCAN_S_APPEARED_SCANNING)
{
[self scan: FALSE];
state = SCAN_S_APPEARED_IDLE;
}
}
- (void) clearPeriphForRow: (NSInteger)row
{
DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row];
//if( (dp.peripheral.isConnected == FALSE) &&
// ( (dp.state == DP_STATE_CONNECTED) || (dp.state == DP_STATE_DISCONNECTING)))
if(dp.peripheral.isConnected == FALSE)
{
dp.state = DP_STATE_IDLE;
}
else if( (dp.peripheral.isConnected == TRUE) &&
(dp.state != DP_STATE_CONNECTED))
{
dp.state = DP_STATE_CONNECTED;
}
if(dp.state == DP_STATE_IDLE)
{
[discoveredPeripherals removeObjectAtIndex:row];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:1];
//ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
//[cell.activityView stopAnimating];
cell.accessoryType = UITableViewCellAccessoryNone;
[self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void) clearPeriph
{
if(self->discoveredPeripherals.count > 0)
{
for(int i = discoveredPeripherals.count - 1; i >= 0 ; i--)
{
[self clearPeriphForRow:i];
}
}
[self.myTableView reloadData];
}
- (IBAction)clearPeripherals:(id)sender {
[self clearPeriph];
[self scan: FALSE];
state = SCAN_S_APPEARED_IDLE;
}
- (NSInteger)getRowForPeripheral: (CBPeripheral*)peripheral
{
NSInteger row = -1;
DiscoveredPeripheral* p;
for(int i = 0; (i < discoveredPeripherals.count) && (row == -1); i++)
{
p = [discoveredPeripherals objectAtIndex:i];
if([peripheral isEqual:p.peripheral] == TRUE)
{
row = i;
}
}
return row;
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSInteger row = [self getRowForPeripheral:peripheral];
if(row != -1)
{
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
//ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = [[NSString alloc] initWithFormat:#"Connected"];
//[cell.activityView stopAnimating];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row];
dp.state = DP_STATE_CONNECTED;
//[peripheral discoverServices:nil];
//[self scan:FALSE];
//[[self navigationController] popViewControllerAnimated:NO];
//[self.delegate didConnectedPeriph:dp];
}
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSInteger row = [self getRowForPeripheral:peripheral];
if(row != -1)
{
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
//ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = [[NSString alloc] initWithFormat:#""];
cell.accessoryType = UITableViewCellAccessoryNone;
//[cell.activityView stopAnimating];
DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row];
dp.state = DP_STATE_IDLE;
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
bool new = TRUE;
DiscoveredPeripheral* discPeripheral;
int row = -1;
if((state == SCAN_S_APPEARED_SCANNING) &&
(peripheral != nil))
{
for(int i = 0; (i < discoveredPeripherals.count) && (new == TRUE); i++)
{
NSLog(#"Scan Ajout periph");
discPeripheral = [discoveredPeripherals objectAtIndex:i];
if(discPeripheral.peripheral == peripheral)
{
new = false;
row = i;
discPeripheral.peripheral = peripheral;
}
}
if(new == TRUE)
{
discPeripheral = [[DiscoveredPeripheral alloc] initWithPeripheral:peripheral andAdvertisment:advertisementData andRssi:RSSI];
discPeripheral.rssi = RSSI;
if(peripheral.isConnected == TRUE)
{
discPeripheral.state = DP_STATE_CONNECTED;
}
[discoveredPeripherals addObject:discPeripheral];
NSLog(#"Scan Ajout periph, total:%i",[discoveredPeripherals count]);
NSLog(#"Scan %i: Add %#",[discoveredPeripherals count]-1, discPeripheral.peripheral.name);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[discoveredPeripherals count]-1 inSection:1];
NSLog(#"Scan Nouveau periph, index:%i, section:%i",indexPath.row,indexPath.section);
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = discPeripheral.peripheral.name;
//[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
discPeripheral.peripheral = peripheral;
discPeripheral.advertisment = advertisementData;
discPeripheral.rssi = RSSI;
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
//ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath];
//NSLog(#"%i: Update %#", row, discPeripheral.peripheral.name);
cell.textLabel.text = discPeripheral.peripheral.name;
//cell.labelInfo.text = [[NSString alloc] initWithFormat:#"RSSI: %#", discPeripheral.rssi];
}
}
}
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSInteger row = [self getRowForPeripheral:peripheral];
if(row != -1)
{
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:row inSection:1];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
//ScanCell* cell = (ScanCell*)[self.tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = [[NSString alloc] initWithFormat:#""];
cell.accessoryType = UITableViewCellAccessoryNone;
//[cell.activityView stopAnimating];
DiscoveredPeripheral* dp = [discoveredPeripherals objectAtIndex:row];
dp.state = DP_STATE_IDLE;
}
}
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
//DiscoveredPeripheral* discPeripheral;
CBPeripheral* peripheral;
for(int i = 0; i < peripherals.count; i++)
{
peripheral = [peripherals objectAtIndex:i];
/*
discPeripheral = [[DiscoveredPeripheral alloc] initWithPeripheral:peripheral andAdvertisment:nil andRssi:nil];
if(peripheral.isConnected == TRUE)
{
discPeripheral.state = DP_STATE_CONNECTED;
}
[discoveredPeripherals addObject:discPeripheral];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[discoveredPeripherals count] - 1 inSection:1];
[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
*/
//[cbCentralManager cancelPeripheralConnection:peripheral];
NSDictionary *dictionary;
dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];
[cbCentralManager connectPeripheral:peripheral options:dictionary];
}
}
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
//NSLog(#"Central Manager State: %d", [central state]);
if(central.state == CBCentralManagerStatePoweredOn)
{
[cbCentralManager retrieveConnectedPeripherals];
}
}
#end
Edit:
This view is called from a view controller.
The view controller is receiving data from bluetooth, record and displays the data.
What I would like to achieve is to have a separate view to connect to the BLE peripheral, go back to the main view, attach the serial port and run.
In a second time, if the peripheral is lost, try to reconnect to it, else pop the connection view and alert the user.
Cheers.
Cedric
You need to retain the peripheral. As soon as the peripheral object you are passed is released, iOS drops the connection. Save the CBPeripheral object in a variable, and be sure to pass that back to your main view when the scan view closes.
A very nice way to manage your entire bluetooth processes is the singleton model. You can move all your bluetooth code to a separate NSObject class and declare that file as a singleton. Create a function within your singleton class to initiate the connectPeripheral after you discover your device. Whenever you connect, you can save the peripheral you are connecting to as a variable or in an array if you have multiple devices. It's quite simple once you get the hang of it. Using this method of implementation you can refer to your connected Peripheral from anywhere within your app. Hope this helped!
Related
I am creating app link food panda.let me explain the flow.I have a vc with table with rows and sections when i click on section it will expand and collapsing rows.in the section there is add button in each rows.wqhen i click on add button in section 3 row the button should hide and + and - button should show like the image given below.
2.when i click on the pluse and minus button it should add to cart and money should increase and decrease amount in cart i used below code for expand and collapse sections.
#implementation menulistingVC
- (void)viewDidLoad {
[super viewDidLoad];
[super viewDidLoad];
menuarray=[[NSMutableArray alloc]init];
arrselectedrow=[[NSMutableArray alloc]init];
defaults = [NSUserDefaults standardUserDefaults];
apiCall = [[APICall alloc]init];
isMultipleExpansionAllowed = NO;
arrSelectedSectionIndex = [[NSMutableArray alloc] init];
if (!isMultipleExpansionAllowed) {
[arrSelectedSectionIndex addObject:[NSNumber numberWithInt:countt+20]];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadtable:)
name:#"array" object:nil];
_tblview.estimatedRowHeight = 69;
_tblview.rowHeight = UITableViewAutomaticDimension;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)loadtable:(NSNotification*)notification
{
isMultipleExpansionAllowed = NO;
arrSelectedSectionIndex = [[NSMutableArray alloc] init];
if (!isMultipleExpansionAllowed) {
[arrSelectedSectionIndex addObject:[NSNumber numberWithInt:countt+20]];
}
[self getingfooddeatilsbacedonclub:[notification object]];
}
-(void)getingfooddeatilsbacedonclub:(NSString *)typestr{
_clubstr = [[NSUserDefaults standardUserDefaults]
stringForKey:#"newclubid"];
// accessToken=[defaults valueForKey:#"accessToken"];
// clubberId = [defaults valueForKey:#"idClubber_dtls"];
if (![APICall hasNetwork])
{
[Util displayToastMessage:#"No internet connection"];
}else
{
[customBezelActivityView activityViewForView:self.view];
NSString *urlstr = [NSString stringWithFormat:#"%s/presignin/menu/list/category/by_venue?clubId=%#&type=%#",urlPath,_clubstr,typestr];
NSLog(#"getherd :%#",urlstr);
[apiCall getArrayFromApiwithstauscode:urlstr restfulType:kRestfulGet andUseContentType:NO withRequestBody:nil completionHandler:^(NSArray *result, NSInteger statuscodeint){
NSLog(#"classifieds List response:%#",result);
NSLog(#"statuscode List response:%ld",(long)statuscodeint);
if (statuscodeint==200) {
dispatch_async(dispatch_get_main_queue(), ^{
[customBezelActivityView removeViewAnimated:YES];
menuarray=[result mutableCopy];
isMultipleExpansionAllowed = NO;
if (!isMultipleExpansionAllowed) {
[arrSelectedSectionIndex addObject:[NSNumber numberWithInt:countt+20]];
}
[_tblview reloadData];
});
}else if (statuscodeint==401){
dispatch_async(dispatch_get_main_queue(), ^{
[customBezelActivityView removeViewAnimated:YES];
UIStoryboard *storyBoard =[UIStoryboard storyboardWithName:#"Main" bundle:nil];
SignInViewController *SignINViewController=[storyBoard instantiateViewControllerWithIdentifier:#"SignINViewController"];
[self presentViewController:SignINViewController animated:YES completion:nil];
});
}
}];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return menuarray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([arrSelectedSectionIndex containsObject:[NSNumber numberWithInteger:section]])
{
NSArray *arr=[menuarray[section] valueForKey:#"menu"];
return arr.count;
}else{
return 0;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MenudetailsTblCell";
menudetailscell = ( MenudetailsTblCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (menudetailscell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MenudetailsTblCell" owner:self options:nil];
menudetailscell = [nib objectAtIndex:0];
}
if (menudetailscell == nil)
{
menudetailscell = [[MenudetailsTblCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
menudetailscell.detailview.layer.cornerRadius = 3.0;
menudetailscell.detailview.layer.masksToBounds = YES;
if (indexPath.row==0) {
menudetailscell.toplbl.hidden=YES;
}else{
menudetailscell.toplbl.hidden=NO;
}
menudetailscell.addbtntocart.layer.cornerRadius = 5.0;
menudetailscell.addbtntocart.layer.masksToBounds = YES;
menudetailscell.addbtntocart.tag=indexPath.row;
menudetailscell.plusebtn.tag=indexPath.row;
menudetailscell.minusbtn.tag=indexPath.row;
menudetailscell.plusebtn.hidden=YES;
menudetailscell.minusbtn.hidden=YES;
menudetailscell.noofitemslbl.hidden=YES;
NSArray *arr=[menuarray[indexPath.section] valueForKey:#"menu"];
menudetailscell.typelbl.text=[[arr objectAtIndex:indexPath.row]valueForKey:#"name"];
menudetailscell.describtionlbl.text=[[arr objectAtIndex:indexPath.row]valueForKey:#"description"];
NSString *cost=[NSString stringWithFormat:#"%#%#",[[arr objectAtIndex:indexPath.row]valueForKey:#"price"],#".00"];
NSString *imgid=[NSString stringWithFormat:#"%#",[[arr objectAtIndex:indexPath.row]valueForKey:#"idmenus"]];
NSString *tax=[NSString stringWithFormat:#"%#",[[arr objectAtIndex:indexPath.row]valueForKey:#"tax"]];
if ([tax isEqualToString:#"tax"]) {
menudetailscell.taxlbl.text=#"(*Inclusive of all taxes)";
}else{
menudetailscell.taxlbl.text=#"(*Exclusive of all taxes)";
}
menudetailscell.ratelbl.text=[NSString stringWithFormat:#"%# %#",[[arr objectAtIndex:indexPath.row]valueForKey:#"country"],cost];
[ menudetailscell.addbtntocart addTarget:self action:#selector(addbtnclicked:)forControlEvents:UIControlEventTouchUpInside];
NSString *typeimgUrl1 = [NSString stringWithFormat:#"%s/presignin/menu/showMedia?idMenu=%#",urlPath,imgid];
NSURL *imageURL=[NSURL URLWithString:typeimgUrl1];
menudetailscell.imgview.imageURL=imageURL;
[menudetailscell.plusebtn addTarget:self action:#selector(pluseTapShowHideSection:) forControlEvents:UIControlEventTouchUpInside];
[menudetailscell.minusbtn addTarget:self action:#selector(minusTapShowHideSection:) forControlEvents:UIControlEventTouchUpInside];
menudetailscell.selectionStyle = UITableViewCellSelectionStyleNone;
return menudetailscell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *CellIdentifier = #"Menusectioncell";
menusectioncell = ( Menusectioncell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (menusectioncell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"Menusectioncell" owner:self options:nil];
menusectioncell = [nib objectAtIndex:0];
}
if (menusectioncell == nil)
{
menusectioncell = [[Menusectioncell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([arrSelectedSectionIndex containsObject:[NSNumber numberWithInteger:section]])
{
// right-arrow //down-arrow
menusectioncell.Sectiomtitlebtn.selected = YES;
menusectioncell.dotlbl.hidden=NO;
menusectioncell.expandtypeimg.image=[UIImage imageNamed:#"down-arrow"];
}
else{
menusectioncell.dotlbl.hidden=YES;
menusectioncell.expandtypeimg.image=[UIImage imageNamed:#"right-arrow"];
}
menusectioncell.Sectiomtitlebtn.tag=section;
menusectioncell.dotlbl.layer.cornerRadius = menusectioncell.dotlbl.frame.size.height/2;
menusectioncell.dotlbl.layer.masksToBounds = YES;
[menusectioncell.Sectiomtitlebtn addTarget:self action:#selector(btnTapShowHideSection:) forControlEvents:UIControlEventTouchUpInside];
NSString *btntitle=[menuarray[section] valueForKey:#"catagory"];
itemarr=[menuarray[section] valueForKey:#"menu"];
NSString *items=[itemarr[0] valueForKey:#"name"];
menusectioncell.sectiontitleilb.text=btntitle;
if (itemarr.count==1) {
menusectioncell.itemslbl.text=[NSString stringWithFormat:#"%#",items];
}else{
NSString *seconditemstr=[itemarr[1] valueForKey:#"name"];
menusectioncell.itemslbl.text=[NSString stringWithFormat:#"%#,%# etc..",items,seconditemstr];
}
menusectioncell.selectionStyle = UITableViewCellSelectionStyleNone;
return menusectioncell.contentView;
}
-(IBAction)btnTapShowHideSection:(UIButton*)sender
{
int section=sender.tag;
if (!sender.selected)
{
//originallcode
if (!isMultipleExpansionAllowed) {
[arrSelectedSectionIndex addObject:#"-1"];
[arrSelectedSectionIndex replaceObjectAtIndex:0 withObject:[NSNumber numberWithInteger:sender.tag]];
}else {
NSLog(#"%#",arrSelectedSectionIndex);
[arrSelectedSectionIndex addObject:[NSNumber numberWithInteger:sender.tag]];
}
menusectioncell.dotlbl.hidden=YES;
menusectioncell.expandtypeimg.image=[UIImage imageNamed:#"right-arrow"];
sender.selected = YES;
}
else{
sender.selected = NO;
menusectioncell.dotlbl.hidden=NO;
menusectioncell.expandtypeimg.image=[UIImage imageNamed:#"down-arrow"];
if ([arrSelectedSectionIndex containsObject:[NSNumber numberWithInteger:sender.tag]])
{
[arrSelectedSectionIndex removeObject:[NSNumber numberWithInteger:sender.tag]];
}
}
if (!isMultipleExpansionAllowed) {
[_tblview reloadData];
}else {
[_tblview reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (void)addbtnclicked:(UIButton *)sender
{
menudetailscell.plusebtn.hidden=NO;
menudetailscell.minusbtn.hidden=NO;
menudetailscell.noofitemslbl.hidden=NO;
menudetailscell.addbtntocart.hidden=YES;
int rowselect=sender.tag;
[arrselectedrow addObject:[NSNumber numberWithInteger:sender.tag]];
NSIndexPath* indexPath1 = [NSIndexPath indexPathForRow:sender.tag inSection:sectionselect];
[self.tblview beginUpdates];
[self.tblview reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath1, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tblview endUpdates];
}
- (void)pluseTapShowHideSection:(UIButton *)sender
{
}
- (void)minusTapShowHideSection:(UIButton *)sender
{
if ([arrselectedrow containsObject:[NSNumber numberWithInteger:sender.tag]])
{
[arrselectedrow removeObject:[NSNumber numberWithInteger:sender.tag]];
}
[self.tblview beginUpdates];
[self.tblview reloadRowsAtIndexPaths:[NSArray arrayWithObjects:arrselectedrow, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tblview endUpdates];
}
Im trying to figure out why my program runs well on simulator but not on Phone.
when i scroll my Tables it gets laggy.
ive tried everything , even removed my Images loading but still scroll lag happen.
Im using apple lazy loading source code :
this is my code :
#define kCustomRowCount 7
#interface SubCategoryViewController () <UIScrollViewDelegate>
#property (nonatomic, strong) NSMutableDictionary *imageDownloadsInProgress;
#property (nonatomic, strong) NSMutableDictionary *imageRestitleDownloadsInProgress;
#property (nonatomic, assign) int intindex;
#end
#implementation SubCategoryViewController
#pragma mark
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = self.catname;
self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
self.imageRestitleDownloadsInProgress = [NSMutableDictionary dictionary];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSArray *allDownloads = [self.imageDownloadsInProgress allValues];
[allDownloads makeObjectsPerformSelector:#selector(cancelDownload)];
NSArray *allDownloads2 = [self.imageRestitleDownloadsInProgress allValues];
[allDownloads2 makeObjectsPerformSelector:#selector(cancelDownload)];
[self.imageDownloadsInProgress removeAllObjects];
[self.imageRestitleDownloadsInProgress removeAllObjects];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger count = [self.entries count];
// if there's no data yet, return enough rows to fill the screen
if (count == 0)
{
return kCustomRowCount;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell2";
NSUInteger nodeCount = [self.entries count];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
UILabel *newsbody = (UILabel *)[cell.contentView viewWithTag:6];
UIImageView *uimg = (UIImageView *)[cell.contentView viewWithTag:20];
UIImageView *uimgresttile = (UIImageView *)[cell.contentView viewWithTag:23];
if (nodeCount == 0 && indexPath.row == 0)
{
if (cell == nil) {
uimg.hidden = true;
uimgresttile.hidden = true;
newsbody.hidden = true;
}
else
{
uimg.hidden = true;
uimgresttile.hidden = true;
newsbody.hidden = true;
}
return cell;
}
if (nodeCount == 0 && indexPath.row > 0)
{
cell.hidden = true;
return cell;
}
if (nodeCount > 0)
{
uimg.hidden = false;
uimgresttile.hidden = false;
newsbody.hidden = true;
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
[newsbody setText:appRecord.Body];
if (!appRecord.appIcon)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
uimg.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
uimg.image = appRecord.appIcon;
}
if (!appRecord.appIconrestitle)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startRestitleIconDownload:appRecord forIndexPath:indexPath];
}
uimgresttile.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
uimgresttile.image = appRecord.appIconrestitle;
}
}
if ((unsigned long)indexPath.row == [self.entries count] - 1){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^{
NewsFetchParseOperation *p = [[NewsFetchParseOperation alloc]init];
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
p.cat = appRecord.Category;
self.intindex = self.intindex + 1;
p.index = [NSString stringWithFormat:#"%d", (int)self.intindex];
p.lastid = appRecord.ids;
[p main];
dispatch_async(dispatch_get_main_queue(), ^(void)
{
SubCategoryViewController *svc =[self.storyboard instantiateViewControllerWithIdentifier:#"SubCategory"];
NSArray *temp =[self.entries arrayByAddingObjectsFromArray:p.appRecordList];
self.entries = temp;
[self.tableView reloadData];
});
});
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
height += 1;
return height;
}
- (void)startIconDownload:(NewsFetchAppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
NewsFetchIconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[NewsFetchIconDownloader alloc] init];
iconDownloader.newsfetchappRecord = appRecord;
[iconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIImageView *uimg = (UIImageView *)[cell.contentView viewWithTag:20];
uimg.image = appRecord.appIcon;
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
- (void)startRestitleIconDownload:(NewsFetchAppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
NewsFetchRestitleIconDownloader *ResttitleiconDownloader = [self.imageRestitleDownloadsInProgress objectForKey:indexPath];
if (ResttitleiconDownloader == nil)
{
ResttitleiconDownloader = [[NewsFetchRestitleIconDownloader alloc] init];
ResttitleiconDownloader.newsfetchappRecord = appRecord;
[ResttitleiconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIImageView *uimgresttile = (UIImageView *)[cell.contentView viewWithTag:23];
uimgresttile.image = appRecord.appIconrestitle;
[self.imageRestitleDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageRestitleDownloadsInProgress setObject:ResttitleiconDownloader forKey:indexPath];
[ResttitleiconDownloader startDownload];
}
}
- (void)loadImagesForOnscreenRows
{
if ([self.entries count] > 0)
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
if (!appRecord.appIcon)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
- (void)loadRestitleImagesForOnscreenRows
{
if ([self.entries count] > 0)
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
if (!appRecord.appIconrestitle)
{
[self startRestitleIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
[self loadImagesForOnscreenRows];
[self loadRestitleImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenRows];
[self loadRestitleImagesForOnscreenRows];
}
#end
Edit:
In iphone if i scroll the the table it will freeze and jump most of time. even when
picture loaded properly. this problem never happen in simulator and only in real device.
i read most of article here base on "uitableview" lagging. most them suggest to use asnyc
method for downloading images. im using apple lazyloading sample method so i guess images
gets downloaded other than main thread.
think i have done till now is to comment most of code section by section and still lag
happend.
i even remove most part from Storyboard , but still lag happend.
You should delete all of your image download methods. Delete also scrollViewDidEndDragging and scrollViewDidEndDecelerating. I don't know why your heightForRowAtIndexPath is so complicated. Is every row a different size? If not use a simple case statement with the couple of cases you've got. Different height for each row can be a drag on resources.
Now for cellForRowAtIndexPath:
If the hidden not hidden stuff you are doing is for performance you should delete all of that.
Add AFNetworking to your project. If you are using cocaopods (you should) can add it with on line in your Podfile. It's good practice when developing with iOS to use libraries and AFNetworking is the best when it comes to getting stuff like images from a network.
#import "UIImageView+AFNetworking.h"
Now all your image work is done with one line of code (AFNetworking will handle all the caching and the performance related issues and the asynchronous stuff for you):
[uimg setImageWithURL:"http://blahbahblah.com" placeholderImage:someUIIMage]
I am trying to implement https://developer.apple.com/library/ios/samplecode/LazyTableImages/Introduction/Intro.html
code for collection view.. Everything is working fine. But in cellForRowAtIndex method while re-loading of old cell the application is crashing. Have a look at code:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:
(NSInteger)section
{
if (self.galleryItemsArray) {
return [self.galleryItemsArray count];
}
else
{
return 0;
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger nodeCount = [self.galleryItemsArray count];
static NSString* simpleTableIdentifier = #"SavedMessageCell_ID";
SavedMessagesCell *cell = [cv dequeueReusableCellWithReuseIdentifier:simpleTableIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[SavedMessagesCell alloc] initWithFrame:CGRectZero];
}
cell.textLabel.text = [NSString stringWithFormat:#"{%ld,%ld}", (long)indexPath.row, (long)indexPath.section];
if(nodeCount>0)
{
GalleryItemDS *item = [self.galleryItemsArray objectAtIndex:indexPath.row];
// Only load cached images; defer new downloads until scrolling ends
if (!item.imageOfItem)
{
if (gallery_collectionView.dragging == NO && gallery_collectionView.decelerating == NO)
{
[self startIconDownload:item forIndexPath:indexPath];
NSLog(#"%#",item.PhotoPath);
}
// if a download is deferred or in progress, return a placeholder image
cell.image.image = [UIImage imageNamed:#"Icon.png"];
}
else
{
NSLog(#"%#",[NSString stringWithFormat:#"{%ld,%ld}", (long)indexPath.row, (long)indexPath.section]);
NSLog(#"%#",item.PhotoPath);
**cell.image.image = item.imageOfItem; // Crashing here**
}
}
return cell;
}
// -------------------------------------------------------------------------------
// startIconDownload:forIndexPath:
// -------------------------------------------------------------------------------
- (void)startIconDownload:(GalleryItemDS *)galleryItem forIndexPath:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.galleryItem = galleryItem;
[iconDownloader setCompletionHandler:^{
SavedMessagesCell *cell = (SavedMessagesCell *)[gallery_collectionView cellForItemAtIndexPath:indexPath];
// Display the newly loaded image
cell.image.image = galleryItem.imageOfItem;
// cell.backgroundColor = [UIColor colorWithPatternImage:galleryItem.imageOfItem];
// Remove the IconDownloader from the in progress list.
// This will result in it being deallocated.
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
- (void)loadImagesForOnscreenRows
{
if ([self.galleryItemsArray count] > 0)
{
NSArray *visiblePaths = [gallery_collectionView indexPathsForVisibleItems];
for (NSIndexPath *indexPath in visiblePaths)
{
GalleryItemDS *appRecord = [self.galleryItemsArray objectAtIndex:indexPath.row];
if (!appRecord.imageOfItem)
// Avoid the app icon download if the app already has an icon
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
#pragma mark - UIScrollViewDelegate
// -------------------------------------------------------------------------------
// scrollViewDidEndDragging:willDecelerate:
// Load images for all onscreen rows when scrolling is finished.
// -------------------------------------------------------------------------------
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
[self loadImagesForOnscreenRows];
}
}
// -------------------------------------------------------------------------------
// scrollViewDidEndDecelerating:
// -------------------------------------------------------------------------------
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenRows];
}
Please help me in it.
How to convert iphone lazytableimages from .xib file to using storyboard? or any sample code using storyboard which are similiar to lazytableimages. The source code from https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
It doesn't matter where the controller's view comes from, be it xib, code or storyboard. The code of the controller does not change in that example's case, just make sure to put scene on storyboard, set it's view controller class and connect all the outlets.
#import "MasterListViewController.h"
#import "AppRecord.h"
#import "RootViewController.h"
#import "ParseOperation.h"
#define kCustomRowHeight 60.0
#define kCustomRowCount 7
static NSString *const TopPaidAppsFeed =
#"http://phobos.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidapplications/limit=75/xml";
#interface MasterListViewController ()
- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath;
#end
#implementation MasterListViewController
#synthesize entries;
#synthesize imageDownloadsInProgress;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
self.tableView.rowHeight = kCustomRowHeight;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSArray *allDownloads = [self.imageDownloadsInProgress allValues];
[allDownloads makeObjectsPerformSelector:#selector(cancelDownload)];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = [entries count];
if (count == 0)
{
return kCustomRowCount;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// customize the appearance of table view cells
//
static NSString *CellIdentifier = #"LazyTableCell";
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell";
// add a placeholder cell while waiting on table data
int nodeCount = [self.entries count];
//NSLog(#"RootViewController - nodeCount is %d",nodeCount);
if (nodeCount == 0 && indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:PlaceholderCellIdentifier];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.detailTextLabel.text = #"Loading…";
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Leave cells empty if there's no data yet
if (nodeCount > 0)
{
// Set up the cell...
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = appRecord.appName;
cell.detailTextLabel.text = appRecord.artist;
// Only load cached images; defer new downloads until scrolling ends
if (!appRecord.appIcon)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
// if a download is deferred or in progress, return a placeholder image
cell.imageView.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
cell.imageView.image = appRecord.appIcon;
}
}
return cell;
}
- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.appRecord = appRecord;
iconDownloader.indexPathInTableView = indexPath;
iconDownloader.delegate = self;
[imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
- (void)loadImagesForOnscreenRows
{
if ([self.entries count] > 0)
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
if (!appRecord.appIcon) // avoid the app icon download if the app already has an icon
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
// called by our ImageDownloader when an icon is ready to be displayed
- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader != nil)
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:iconDownloader.indexPathInTableView];
// Display the newly loaded image
cell.imageView.image = iconDownloader.appRecord.appIcon;
}
// Remove the IconDownloader from the in progress list.
// This will result in it being deallocated.
[imageDownloadsInProgress removeObjectForKey:indexPath];
}
// Load images for all onscreen rows when scrolling is finished
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
[self loadImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenRows];
}
#end
I am writing a google reader application and have been trying to create the settings table view with UISwitch. Below is the complete code sequence:
#implementation Settings
#synthesize rowImage;
#synthesize ViewPushed;
#synthesize alreadySignedIn;
#synthesize syncStartupSwitch;
#synthesize confirmMarkSwitch;
#synthesize landscapeModeSwitch;
#synthesize appBadgeSwitch;
#synthesize fontSwitch;
#synthesize newItemsSwitch;
#pragma mark -
#pragma mark View lifecycle
static SEL syncStartup;
static SEL markAsReadConfirm;
static SEL landscapeMode;
static SEL appBadge;
static SEL fontSettings;
static SEL newItemsFirstSel;
+(void) initialize{
syncStartup = #selector(syncAtStartup:);
markAsReadConfirm = #selector (confirmMarkAsRead:);
landscapeMode = #selector (landscapeMode:);
appBadge = #selector (appBadgeSetting:);
fontSettings = #selector (largeFontSetting:);
newItemsFirstSel = #selector (newItemFirst:);
}
-(void) newItemFirst:(id)sender {
if ([sender isOn]) {
newItemsSwitch = YES;
}else {
newItemsSwitch = NO;
}
}
-(void) syncAtStartup:(id)sender {
if ([sender isOn]) {
syncStartupSwitch = YES;
}else {
syncStartupSwitch = NO;
}
}
-(void) confirmMarkAsRead:(id)sender{
if ([sender isOn]) {
confirmMarkSwitch = YES;
}else {
confirmMarkSwitch = NO;
[self.tableView reloadData];
}
}
-(void) landscapeMode:(id)sender{
if([sender isOn]) {
landscapeModeSwitch = YES;
}else {
landscapeModeSwitch = NO;
}
}
-(void) appBadgeSetting:(id)sender{
if([sender isOn]) {
appBadgeSwitch = YES;
}else {
appBadgeSwitch = NO;
}
}
-(void) largeFontSetting:(id)sender{
if ([sender isOn]) {
[UIFont systemFontOfSize:32];
fontSwitch = YES;
NSLog(#"YES");
}else {
fontSwitch = NO;
NSLog(#"YES");
}
}
/*
-(void) saveLastViewedItem{
[plistData setValue:[[[UIApplication sharedApplication]delegate]currentItemID]forKey:keyLastItemID];
[plistData setValue:[[[[[[[UIApplication sharedApplication]delegate]navController]navController]topViewController]delegate]tag]forKey:keyLastItemTag];
}
-(void) save {
[self saveLastViewedItem];
BOOL success = [plistData writeToFile:[docsPath stringByAppendingPathComponent:plistName] atomically:YES];
if (!success) {
NSLog(#"FAILED saving plist");
}else {
dbg_s(#"saved data:%# to file: %#", plistData, [docsPath stringByAppendingPathComponent:plistName]);
}
}
-(void) load{
dbg(#"loading plist data from path: %#", [docsPath stringByAppendingPathComponent:plistName]);
plistData = [[NSMutableDictionary dictionaryWithContentsOfFile:[docsPath stringByAppendingPathComponent:plistName]]retain];
if(!plistData){
NSLog(#"FAILED loading plist");
plistData = [[NSMutableDictionary dictionary] retain];
}
dbg_s(#"Loaded plist data", plistData);
dbg_s("%#", plistData);
[self removeDeprecatedProperties];
[self loadFeedList];
}
-(void) removeDeprecatedProperties{
for (NSString * deprecatedProperty in deprecatedProperties){
[plistData removeObjectForKey:deprecatedProperty];
}
}
-(void) reloadFeedList{
[self loadFeedList];
[self setUIElements];
}
-(NSArray *) loadFeedList {
NSString *contents = [NSString stringWithContentsOfFile:[docsPath stringByAppendingPathComponent:#"tagList"]encoding:NSUTF8StringEncoding error:nil];
id result;
if(!contents) {
dbg(#"no feed list loaded");
result = nil;
}else {
NSArray *originalList = [contents componentsSeparatedByString:#"\n"];
NSMutableArray *feedList = [NSMutableArray arrayWithCapacity:[originalList count]];
for (NSString *feed in originalList) {
NSString *trimmedFeed = [feed stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if([feed length] > 0){
[feedList addObject:trimmedFeed];
}
}
result = feedList;
}
[possibleTags release];
possibleTags = [result retain];
return result;
}
-(NSArray *)feedList {
return possibleTags;
}
-(NSArray *) activeTagList {
id tags = [self tagList];
NSArray *result = [NSMutableArray arrayWithCapacity:[tags count]];
for (NSString *tag in tags) {
if([possibleTags containsObject:tag]) {
[result arrayByAddingObject:tag];
}
}
return result;
}
-(id) init{
self =[super init];
plistName = #"config.plist";
if (openLinksInSegmentValues == nil)
openLinksInSegmentValues = [[NSArray alloc] initWithObjects:openLinksInAskMeValue, openLinksInSafariValue, openLinksIniReaderValue, nil];
if (deprecatedProperties == nil)
deprecatedProperties = [[NSArray alloc] initWithObjects:#"openInSafari", nil];
[self docsPath];
[self load];
return self;
}
*/
- (void)viewDidLoad {
syncSwitch=[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
readSwitch=[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
landscapeSwitch=[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
badgeSwitch=[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
largeFontSwitch=[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
newItemsFirstSwitch =[[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
//switcher = [[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
NSString *loginData;
NSError *keychainError;
NSString *checkUsername= [SFHFKeychainUtils getPasswordForUsername:#"Username" andServiceName:#"iReader" error:&keychainError];
NSString *checkPassword = [SFHFKeychainUtils getPasswordForUsername:#"Password" andServiceName:#"iReader" error:&keychainError];
if (checkPassword == nil || checkUsername == nil) {
alreadySignedIn = NO;
loginData = #"Sync Settings";
} else {
alreadySignedIn = YES;
loginData = #"Logout";
}
if(ViewPushed == NO) {
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(cancel_Clicked:)] autorelease];
}
listOfItems = [[NSMutableArray alloc] init];
NSArray *syncSettingsToLoad = [NSArray arrayWithObjects:loginData, nil];
NSDictionary *syncSettingsToLoadDict = [NSDictionary dictionaryWithObject:syncSettingsToLoad forKey:#"Settings"];
NSArray *generalSetting = nil;
generalSetting = [NSArray arrayWithObjects:#"Sync at Startup",#"Confirm Mark as Read", #"Landscape Mode", #"Cache Settings",nil];
NSMutableDictionary *generalSettingsDict = [NSMutableDictionary dictionaryWithObject:generalSetting forKey:#"Settings"];
NSArray *appearanceSettings = [NSArray arrayWithObjects:#"New Items First", #"App Icon Badge", #"Large Font", nil];
NSDictionary *appearanceSettingsDict = [NSDictionary dictionaryWithObject:appearanceSettings forKey:#"Settings"];
NSArray *sharingSettings = [NSArray arrayWithObjects:#"Customize Sharing Options", nil];
NSDictionary *sharingSettingsDict = [NSDictionary dictionaryWithObject:sharingSettings forKey:#"Settings"];
NSArray *advancedSettings = [NSArray arrayWithObjects:#"Advanced Options", nil];
NSDictionary *advancedSettingsDict = [NSDictionary dictionaryWithObject:advancedSettings forKey:#"Settings"];
[listOfItems addObject:syncSettingsToLoadDict];
[listOfItems addObject:generalSettingsDict];
[listOfItems addObject:appearanceSettingsDict];
[listOfItems addObject:sharingSettingsDict];
[listOfItems addObject:advancedSettingsDict];
self.title =#"Settings";
// Uncomment the following line to preserve selection between presentations.
//self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
[super viewDidLoad];
}
//defaultDatabase = [[userPrefs valueForKey:MAPref_DefaultDatabase] retain];
-(void) cancel_Clicked:(id)sender
{
[self.navigationController dismissModalViewControllerAnimated:YES];
}
- (void)viewWillAppear:(BOOL)animated {
//[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
/*
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return [listOfItems count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSDictionary *dictionary = [listOfItems objectAtIndex:section];
NSArray *array = [dictionary objectForKey:#"Settings"];
return [array count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:
(NSInteger) section {
if (section == 0) {
return #"Sync Settings";
}
if (section == 1) {
return #"General Options";
}
if (section == 2) {
return #"Appearance Options";
}
if (section == 3){
return #"Sharing Options";
}
if (section == 4){
return #"Advanced Options";
}
return nil;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(#"This is what we are looking for %# %#", checkUsername, checkPassword);
// Configure the cell...
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array =[dictionary objectForKey:#"Settings"];
NSString * cellValue = [array objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.section == 0 && indexPath.row == 0) {
static NSString *SomeIdentifierA = #"SomeIdentifierA";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierA];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierA] autorelease];
cell.accessoryType = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text =cellValue;
return cell;
}
else if (indexPath.section ==1 && indexPath.row ==0) {
static NSString *SomeIdentifierB = #"SomeIdentifierB";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierB];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierB] autorelease];
[syncSwitch addTarget:self action:#selector(syncAtStartup:) forControlEvents:UIControlEventValueChanged];
//[cell.contentView addSubview:syncSwitch];
cell.accessoryView = syncSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//cell.reuseIdentifier = #"Cell1";
}
cell.textLabel.text =#"Sync at Startup";
return cell;
}
else if(indexPath.section == 1 && indexPath.row == 1){
static NSString *SomeIdentifierC = #"SomeIdentifierC";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierC];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierC] autorelease];
[readSwitch addTarget:self action:#selector(confirmMarkAsRead:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = readSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text =#"Confirm Mark as Read";
return cell;
}
else if(indexPath.section == 1 && indexPath.row == 2){
static NSString *SomeIdentifierD = #"SomeIdentifierD";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierD];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierD] autorelease];
[landscapeSwitch addTarget:self action:#selector(landscapeMode:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = landscapeSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text =#"Landscape Mode";
return cell;
}
else if (indexPath.section == 1 && indexPath.row == 3) {
static NSString *SomeIdentifierE = #"SomeIdentifierE";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierE];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierE] autorelease];
cell.accessoryType = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text =#"Cache Settings";
return cell;
}
else if (indexPath.section == 1 && indexPath.row == 4) {
static NSString *SomeIdentifierJ = #"SomeIdentifierJ";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierJ];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierJ] autorelease];
cell.accessoryType = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text =#"Caches";
return cell;
}
else if(indexPath.section == 2 && indexPath.row == 0){
static NSString *SomeIdentifierN = #"SomeIdentifierF";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierN];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierN] autorelease];
[newItemsFirstSwitch addTarget:self action:#selector(newItemFirst:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = newItemsFirstSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text =#"App Icon Badge";
return cell;
}
else if(indexPath.section == 2 && indexPath.row == 1){
static NSString *SomeIdentifierF = #"SomeIdentifierF";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierF];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierF] autorelease];
[badgeSwitch addTarget:self action:#selector(appBadgeSetting:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = badgeSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text =#"App Icon Badge";
return cell;
}
else if(indexPath.section == 2 && indexPath.row == 2){
static NSString *SomeIdentifierG = #"SomeIdentifierG";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierG];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierG] autorelease];
[largeFontSwitch addTarget:self action:#selector (largeFontSetting:) forControlEvents:UIControlEventValueChanged];
//[largeFontSwitch addTarget:self action:#selector(largeFontSetting:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = largeFontSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text =#"Large Font Size";
return cell;
}
else if (indexPath.section == 3 && indexPath.row == 0) {
static NSString *SomeIdentifierH = #"SomeIdentifierH";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierH];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierH] autorelease];
cell.accessoryType = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text =#"Customize Sharing Options";
return cell;
}
else if (indexPath.section == 4 && indexPath.row == 0) {
static NSString *SomeIdentifierI = #"SomeIdentifierI";
// This could be some custom table cell class if appropriate
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SomeIdentifierI];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierI] autorelease];
cell.accessoryType = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text =#"Advanced Options";
return cell;
}
//switcher.on = [[NSUserDefaults standardUserDefaults]boolForKey:#"Settings"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:13];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.section ==0){
if (alreadySignedIn == NO) {
if(indexPath.section == 0 && ivControllerCell == nil ){
[tableView reloadData];
ivControllerCell = [[GoogleClientLogin alloc] initWithNibName:#"GoogleClientLogin" bundle:[NSBundle mainBundle]];
ivControllerCell.ViewPushed = YES;
//Push the view controller to the top of the stack.
[self.navigationController pushViewController:ivControllerCell animated:YES];
[ivControllerCell release];
ivControllerCell = nil;
}
}
if (alreadySignedIn ==YES) {
NSError *keyChainEmpty;
[SFHFKeychainUtils deleteItemForUsername:#"Username" andServiceName:#"iReader" error:&keyChainEmpty];
[SFHFKeychainUtils deleteItemForUsername:#"Password" andServiceName:#"iReader" error:&keyChainEmpty];
ivControllerCell = [[GoogleClientLogin alloc] initWithNibName:#"GoogleClientLogin" bundle:[NSBundle mainBundle]];
ivControllerCell.ViewPushed = YES;
[self.navigationController pushViewController:ivControllerCell animated:YES];
}
}
}
-(void) removeSelfFromWindow
{/*
if(self.view.superview){
[UIView beginAnimations:#"curldown" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:NO];
[self.view.superview removeFromSuperview];
}
[UIView commitAnimations];
*/}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
/*static Settings * _standardSettings = nil;
+(Settings *)standardSettings
{
if (_standardSettings == nil)
_standardSettings = [[Settings alloc] init];
return _standardSettings;
}*/
-(void) setUIElements {
[landscapeSwitch setOn:[self landscapeModeSwitch]];
//[feedList setSelectedFeeds:[self taglist]];
}
- (void)dealloc {
[self save];
[plistData release];
[plistName release];
[super dealloc];
}
#end
I am getting the following error when I start scrolling the table view.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType addTarget:action:forControlEvents:]: unrecognized selector sent to instance 0x5f463e0'
Can somebody please help me with this error?
Cheers
Don't autorelease the switches when you alloc them. After those lines you don't own any of those objects.
syncSwitch=[[UISwitch alloc] initWithFrame:CGRectZero];
Release them in the dealloc method
[syncSwitch release];