Sample Application for SQLite - iphone

Hello friends
I am developing application in which view has one textField & 2 buttons. When user clicks on "Add" then text from textfield should be stored in datatabse. When user clicks on "Display"then data fetched from database should be displayed in textField. The code written is like this
//SettingsApplicationViewController.h
#import "FMDatabase.h"
#interface SettingsApplicationViewController : UIViewController {
FMDatabase *db;
IBOutlet UITextField *urlField;
IBOutlet UIButton *insertButton;
IBOutlet UIButton *displayButton;
}
#property(nonatomic, retain) IBOutlet UITextField *urlField;
#property(nonatomic, retain) IBOutlet UIButton *insertButton;
#property(nonatomic, retain) IBOutlet UIButton *displayButton;
-(void)insertButtonClicked :(id)sender;
-(void)displayButtonClicked:(id)sender;
-(id)initApp;
#end
// SettingsApplicationViewController.m
#import "SettingsApplicationViewController.h"
#import "FMDatabase.h"
#implementation SettingsApplicationViewController
#synthesize urlField;
#synthesize insertButton;
#synthesize displayButton;
-(id)initApp
{
if(![super init])
return nil;
//DB stored in application bundle
NSString *DBName = #"SettingDB.sqlite";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingString:DBName];
db = [FMDatabase databaseWithPath:path];
[db setLogsErrors:TRUE];
[db setTraceExecution:TRUE];
if(![db open])
{
NSLog(#"Could not open Database");
return 0;
}
else
{
NSLog(#"Database opened successfully");
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self initApp];
}
-(void)insertButtonClicked :(id)sender
{
[db executeUpdate:#"insert into Settings values (?)",urlField.text];
[self resignFirstResponder];
}
-(void)displayButtonClicked:(id)sender
{
NSString *returnResult = [[NSString alloc]init];
FMResultSet *rs = [db executeQuery:#"select url from Settings"];
while ([rs next])
{
returnResult = [rs stringForColumn:#"url"];
[urlField setText:returnResult];
}
}
// SettingDB.sqlite
CREATE TABLE Settings(url text(50));
I created connections in IB & copied libsqlite3.dylib & FMDatabase file. I dont know why " # " is not printed in this post but I have # in my code.
When I compile this code it is showing 1 error as follows
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1
Please help me friends.
Thanks

This error is usually displayed when you are referring to a file in Xcode and that file not in the mentioned path. (That file will be shown red in the Project Navigator)

Have you assigned Action for those buttons?
If not do as follows,
Instead of -(void)insertButtonClicked :(id)sender; use -(IBAction)insertButtonClicked :(id)sender; and assign them to respective button action.
or else,
In viewdidLoad,
[insertButton addTarget:self action:#selector(insertButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[displayButton addTarget:self action:#selector(displaytButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

Related

Xcode 5 iPhone app; all my '[' and ']' match, but "parse expected ']' " still comes up [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
i'm new and learning from a tutorial, i've coded in python before so i have mercilessly hunted for the additional ']' it claims it needs… and even when i put it in it then says, it's unexpected and want to delete it, leading back to the original problem. it says it expects a ']' on the line "- (void)createOrOpenDB" this is the view controller.m
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *ArrayOfPowders;
sqlite3 *powderDB;
NSString *dbPathSring;
}
- (IBAction)AddPowderButton:(id)sender;
- (IBAction)DeletePowderButton:(id)sender;
- (IBAction)ShowAllButton:(id)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
ArrayOfPowders = [[NSMutableArray alloc]init];
[[self mytableview]setDelegate:self];
[[self mytableview]setDataSource:self];
[self createOrOpenDB];
}
- (void)createOrOpenDB
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathSring = [docPath stringByAppendingPathComponent:#"powders.db"];
char *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:dbPathSring]) {
const char *dbpath = [dbPathSring UTF8String];
// create db here
if (sqlite3_open(dbpath, &powderDB)==SQLITE_OK){
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS POWDERS (ID INTEGER PRIMARY KEY AUTOINCREMENT, POWDERNAME TEXT, RALCODE INTEGER, FINISH TEXT)";
sqlite3_exec(powderDB, sql_stmt, NULL, NULL, &error);
sqlite3_close(powderDB);
}
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [ArrayOfPowders count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell){
Cell = [[UITableViewCell alloc]initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:CellIdentifier];
powder *apowder = [ArrayOfPowders objectAtIndex:indexPath.row];
Cell.textLabel.text = apowder.name;
Cell.detailTextLabel.text = [NSString stringWithFormat:#"%d",apowder.RAL];
return Cell;
}
- (void)didReceiveMemoryWarning
{
[super didRecieveMemoryWarning];
}
- (IBAction)addpowderbutton:(id)sender
{
if (sqlite3_open([dbPathSring UTF8String], &powderDB)==SQLITE_OK){
NSString *inserStmt = [NSString stringWithFormat:#"INSERT INTO POWDERS(NAME,RAL) values ('%s' '%d')",[self.nameField.text UTF8String],[self.RAlField.text intValue]];
const char *insert_stmt = [inserstmt UTF8String];
if (sqlite3_exec(powderDB, insert_stmt, NULL, NULL, &error)==SQLITE_OK) {
NSLog(#"powder added");
powder *powder = [[powder alloc]init];
[powder setname:self.namefield.text];
[powder setRALcode:[self.RALfield.text intValue]];
[ArrayOfPowders addObject:powder];
}
sqlite3_close(powderDB);
}
}
}
- (IBAction)deletepowderbutton:(id)sender {
sqlite3_stmt *statement;
}
- (IBAction)showallpowdersbutton:(id)sender {
}
- (IBAction)AddPowderButton:(id)sender {
}
- (IBAction)DeletePowderButton:(id)sender {
}
- (IBAction)ShowAllButton:(id)sender {
}
#end
viewcontroller.h is;
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#import "powder.h"
#interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITextField *namefield;
#property (weak, nonatomic) IBOutlet UITextField *RALfield;
#property (weak, nonatomic) IBOutlet UITableView *mytableview;
// items on main storyboard are give properties here
#end
On the method createOrOpenDB you are missing a closing } all you need to do is add it at the end like below (As long as this isn't a typo on the copying over to here)
- (void)createOrOpenDB
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathSring = [docPath stringByAppendingPathComponent:#"powders.db"];
}
UPDATE
Just because of how you have named ArrayOfPowders we can tell you aren't familiar with coding conventions so I am going to include Apples Programming with Objective-c conventions documentation that I would recommend you have a read of as it will provide a better understanding of when to use uppercase and lowercase, method names, variable names etc
Change your this code with
- (void)createOrOpenDB
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathSring = [docPath stringByAppendingPathComponent:#"powders.db"];
to
- (void)createOrOpenDB
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathSring = [docPath stringByAppendingPathComponent:#"powders.db"];
}
As you forgot to close the function with "}"

issue regarding property of class shows null

i am making game in which i am not using navigation controller but hiding and unhiding different controllers now my problem is as below
This Is going to be view long description you can understand what i am talking about
my flowConverViewController is like this
#import <UIKit/UIKit.h>
#import "FlowCoverView.h"
#import "NewGameController.h"
#import "MenuController.h"
#class NewGameController;
#interface FlowCoverViewController : UIViewController <FlowCoverViewDelegate>
{
}
#property (nonatomic, strong) NewGameController *game;
- (IBAction)done:(id)sender;
#end
flowcontroller.m is like below
when user click on image then image get selected and game should get start
for that delegate method get called which is below
- (void)flowCover:(FlowCoverView *)view didSelect:(int)image
{
NSLog(#"Selected Index %d",image);
UIImage *newimage = [self flowCover:view cover:image];
[
NSLog(#"%#",[self.game menu]); // this shows null
NSLog(#"%#",self.game); // this shows null thats why my below methods which are in another class is not getting called
[self.game menu] playMenuSound];
// game is object of newGameController that we created in .h file and in
same way in newgamecontroller there is object properly of menu class and
playMenuSound is method in menu class
[self.game imagePickedFromPuzzleLibrary:newimage];
[self.game startNewGame];
}
only problem is this methods are not getting called as it shows null i know that i can alloc init them but i cant do that previous data will get lost i have alloc init this properties in previous classes
.
newgamecontroller.h
#property (nonatomic, assign) MenuController *menu;
newgamecontroller.m
{
FlowCoverViewController *c = [[FlowCoverViewController alloc] init];
c.game = self;
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"TestFC" owner:self options:nil];
c = [array objectAtIndex:0];
[self presentModalViewController:c animated:YES];
}
I'm sorry, you do:
FlowCoverViewController *c = [[FlowCoverViewController alloc] init];
c.game = self;
and then you assign to c a different object with:
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"TestFC" owner:self options:nil];
c = [array objectAtIndex:0];
[self presentModalViewController:c animated:YES];
How could c still have the property c.game set properly??
EDIT: Try instead
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"TestFC" owner:self options:nil];
FlowCoverViewController *c = [array objectAtIndex:0];
[self presentViewController:c animated:YES completion:nil]
and let me know.

writing data using NSKeyedArchiver

I trying to learn how to save array of objects using NSKeyedArchiver and I coded a small application to do that and I logged to see if the array was saved but everytime I get 0 for array count and here is the code.
ViewController.h
#interface ViewController : UIViewController
{
IBOutlet UITextField *text;
IBOutlet UITextField *textName;
IBOutlet UITextField *textAge;
IBOutlet UILabel *name;
IBOutlet UILabel *age;
BOOL flag;
BOOL choice;
NSString *documentDirectory;
NSMutableArray *anArray;
Person *p;
NSData *data;
}
-(BOOL) dataFilePath;
-(IBAction)readPlist;
-(IBAction) writePlist;
#property (strong,nonatomic)IBOutlet UITextField *text;
#property (strong,nonatomic)IBOutlet UITextField *textName;
#property (strong,nonatomic)IBOutlet UITextField *textAge;
#property (strong,nonatomic)IBOutlet UILabel *name;
#property (strong,nonatomic)IBOutlet UILabel *age;
#property (strong,nonatomic)NSString *documentDirectory;
#property (strong,nonatomic)NSMutableArray *anArray;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
#synthesize text,documentDirectory,textAge,textName,name,age,anArray;
- (void)viewDidLoad
{
[super viewDidLoad];
// checking if the file was created and show a message if its created or not.
if ([self dataFilePath]) {
NSLog(#"File Created !");
} else {
NSLog(#"File Not Created !");
}
NSLog(#"File location : %#",documentDirectory);
choice = YES;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL) dataFilePath
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentDirectory = [path objectAtIndex:0];
documentDirectory = [documentDirectory stringByAppendingPathComponent:#"Milmers­Data.dat"];
return TRUE;
}
- (IBAction)writePlist
{
p.name = textName.text;
p.age = [textAge.text intValue];
[anArray addObject:p];
for (int i=0; i<[anArray count]+1; i++) {
Person *pp = [[Person alloc]init];
pp=[anArray objectAtIndex:i];
NSLog(#"Name: %#",pp.name); // checking the names in pp object but getting null
}
data = [NSKeyedArchiver archivedDataWithRootObject:anArray];
[data writeToFile:documentDirectory options:NSDataWritingAtomic error:nil];
NSLog(#"Array length: %d",[anArray count]); //Always got array count zero.
}
-(IBAction)readPlist
{
NSString *filePath = documentDirectory;
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(#"The array is: %#",array); // it shows that there is nothing in the array
}
#end
I wrote the class for writing .plist files originally but I knew later that I cant store objects in .plist file so I tried so that with archive, thats why the method name have plist in it.
Thank you in advance
Looks like you aren't ever creating an instance of p to add to the array. Try:
Person *p = [[Person alloc] init];
p.name = textName.text;
p.age = [textAge.text intValue];
[anArray addObject:p];
your index limit was also wrong in this loop
for (int i=0; i<[anArray count]; i++) {
NSLog(#"Name: %#", [[anArray objectAtIndex:i] name]);
}
you should really have been seeing a couple of different crashes...
Try adding this in viewDidLoad
[[NSFileManager defaultManager] createFileAtPath:documentDirectory contents:nil error:nil];
It looks like you never do this, and using archives to write to files only works if the file already exists (make sure you only do this once, otherwise every time that view is loaded the file will be emptied of all the data in it). And when you do this
if ([self dataFilePath])
It's pointless, because no matter what it always returns yes, whether the file exists or not.
Does your Person class implement NSCoding?
Specifically you need to implement something like the following in Person.m:
- (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
if (!self) {
return nil;
}
self.name = [decoder decodeObjectForKey:#"name"];
self.age = [decoder decodeObjectForKey:#"age"];
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.name forKey:#"name"];
[encoder encodeObject:self.age forKey:#"age"];
}

Getting error class is not key value coding-compliant for the key name

I am implementing SearchBar in my TableView. But it will display error when i try to enter text in SearchBar.
This is my NSObject class code .h file :
#import <Foundation/Foundation.h>
#interface ChannelList : NSObject
{
NSString *channelLink;
NSString *channelName;
NSString *channelType;
NSString *channelLogo;
}
#property (nonatomic, copy) NSString *channelName;
#property (nonatomic, copy) NSString *channelType;
#property (nonatomic, copy) NSString *channelLogo;
#property (nonatomic, copy) NSString *channelLink;
+ (id)channelLink:(NSString*)channelLink channelName:(NSString*)achannelName channelType:(NSString*)achannelType channelLogo:(NSString*)achannelLogo;
#end
And .m file :
#import "ChannelList.h"
#implementation ChannelList
#synthesize channelLogo,channelName,channelType,channelLink;
+ (id)channelLink:(NSString*)channelLink channelName:(NSString*)achannelName channelType:(NSString*)achannelType channelLogo:(NSString*)achannelLogo{
ChannelList *ChannelList = [[self alloc] init];
[ChannelList setChannelLink:channelLink];
[ChannelList setChannelName:achannelName];
[ChannelList setChannelType:achannelType];
[ChannelList setChannelLogo:achannelLogo];
return ChannelList;
}
#end
Using this array to populate my table view
channelAllData = [NSArray arrayWithObjects:
[ChannelList channelLink:#"http://cdn.m.yuppcdn.net/liveorigin/smil:ndtvhindi_iphone.smil/playlist.m3u8" channelName:#"NDTV" channelType:#"NEWS" channelLogo:#"ndtv.png"],[ChannelList channelLink:#"http://cdn.m.yuppcdn.net/liveorigin/smil:aajtak_iphone.smil/playlist.m3u8" channelName:#"Aaj_Tak" channelType:#"NEWS" channelLogo:#"Aaj_Tak"],[ChannelList channelLink:#"http://cdn.m.yupptv.tv/liveorigin/smil:indiatv.smil/playlist.m3u8" channelName:#"India_tv" channelType:#"NEWS" channelLogo:#"India_tv_logo.gif"],[ChannelList channelLink:#"http://cdn.m.yuppcdn.net/liveorigin/smil:headlinetoday_iphone.smil/playlist.m3u8" channelName:#"HeadlinesToday" channelType:#"NEWS" channelLogo:#"HeadlinesToday.png"],nil];
searchedData = [NSMutableArray arrayWithCapacity:[channelAllData count]];
Here searchedData is the search result of my SearchBar.
And here I'm populating my searchedData, and getting error as I mentioned in title.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
// remove all data that belongs to previous search
[searchedData removeAllObjects];
if([searchText isEqualToString:#""]||searchText==nil){
[self.tableView reloadData];
return;
}
[self filterContentForSearchText:searchText];
// NSLog(#"%i",searchedData.count);
[self.tableView reloadData];
}
- (void)filterContentForSearchText:(NSString*)asearchText
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name contains[c] %#",asearchText];
NSLog(#"predicate %#",predicate);
NSArray *tempArray = [channelAllData filteredArrayUsingPredicate:predicate];
searchedData = [NSMutableArray arrayWithArray:tempArray];
}
In the predicate, you're using self.name whereas there's no name property declared on your class. Did you mean self.channelName instead?

accessing class file crashes when scrolling starts (UIScrollview)

hopefully someone will be able to help me. I have a UIScrollView on my page. The .h file has set the UIscrollviewdelegate.
I have a class file called "Picture.h / Picture.m".
- (id)initWithName:(NSString *)aName filename:(NSString *)aFilename {
self.name = aName;
self.filename = aFilename;
return self;
}
In this class file, I simply set a couple of strings. I load an array with object of this picture class, for example
Picture *image2 = [[Picture alloc] initWithName:#"Apple" filename:#"apple.png"];
[pictureArray addObject: image2];
[image2 release];
Within my viewController, I call this class and assign is as such
Picture *thisPicture = (Picture *)[appDelegate.pictureArray objectAtIndex:0];
view2image.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", thisPicture.filename]];
The above works fine. The image is set to what ever I put, example, "apple.png". However, when I tried to set this in the - (void) scrollViewDidScroll:(UIScrollView *) method within my viewController, I get a bad exec error and the app crashes.
Yet, if I had an array of filenames (so not storing my class object in the array) and access objectAtIndex:0 in the scrollViewDidScroll - it works fine.
So, this code is OK
nextImageView.image = [UIImage imageNamed: [NSString stringWithFormat:#"%#", [appDelegate.pictureCardsArray objectAtIndex:0]]];
but this crashes
Picture *image3 = (Picture *)[appDelegate.pictureArray objectAtIndex:0];
nextImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", image3.filename]];
Interestingly though, if I don't try to access the element of image3 (eg image3.filename) it doesn't crash. This is useless though! Also, if I disable the delegate = self for the uiscrollview, then this code works, but none of the scrolling actions are fired. I came across this post (http://stackoverflow.com/questions/1734720/uiscrollview-on-a-uiviewcontroller) when searching for the solution, but cannot see where I might be releasing the viewController early. To be safe, nothing is getting released (yet!)
Hopefully someone might be able to shed some light on it!!
[edit]Just adding in the full class files][/edit]
Picture.h
#import <UIKit/UIKit.h>
#interface Picture : NSObject {
NSString *name;
NSString *filename;
}
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *filename;
- (id)initWithName:(NSString *)aName filename:(NSString *)aFilename;
#end
Picture.m
#import "Picture.h"
#implementation Picture
#synthesize name, filename;
- (id)initWithName:(NSString *)aName filename:(NSString *)aFilename {
self.name = aName;
self.filename = aFilename;
return self;
}
#end
Just for completeness... the solution was as Antwen Van Houdt said - I changed copy to retain and it worked fine.
#import <UIKit/UIKit.h>
#interface Picture : NSObject {
NSString *name;
NSString *filename;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *filename;
- (id)initWithName:(NSString *)aName filename:(NSString *)aFilename;
#end