Cannot find error with SQLITE statement call - xcode

I am having a problem locating my error. The code gets through the ID(init) okay and I know the database is loading. My issue is with the IF(sqlite3_prepare_v2...) statement. When I run the code this line does not ==SQLITE_OK and it jumps to the end. ANy help is appreciated. Thanks.
#implementation CityState
static CityState *WDdatabase;
+(CityState *)WDdatabase {
if(WDdatabase == nil) {
WDdatabase = [[CityState alloc] init];
}
return WDdatabase;
}
- (id)init {
self = [super init];
if (self) {
NSString *sqliteDB = [[NSBundle mainBundle] pathForResource:#"CityAndState" ofType:#"sqlite"];
if(sqlite3_open([sqliteDB UTF8String], &WDdatebase) != SQLITE_OK){
NSLog(#"Failed to open database");
}
}
return self;
}
-(NSArray *)getAllCities {
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
NSString *query = #"SELECT * FROM Test_Table";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(WDdatebase, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
}
sqlite3_finalize(statement);
}
return returnArray;
}

As far as I know, Objective-C does not do static class variables as you are attempting, and the symbol WDatabase (I'm assuming the typo is just here on SO, not in your code) is actually a class identifier instead of your static variable. To implement a singleton, you will need a file-scope variable (outside of the #implementation block) (and I recommend you name it starting with an underscore to clarify when you are accessing that and when you are accessing the class method. So basically, the call you are failing is likely because you are passing a class object instead of your var. Once you have setup the static var properly.
The proper syntax then for accessing a "class variable" (which end up being just a file-scope/statically-stored variable, by virtue of Objective-C's C soul), is to send a message to the class object:
sqlite3_prepare_v2([CityState wDdatebase], [query UTF8String], ...
Further, and just to be pedantic; if you are not using any of NSString's features and only need UTF8 (or "C-style") strings, you can use them just as you would in C:
-(NSArray *)getAllCities {
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
char query[] = "SELECT * FROM Test_Table";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2([CityState wDdatebase], query, -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
}
sqlite3_finalize(statement);
}
return returnArray;
}

Related

Instance variable (NSString) wont change in custom class

I've created a class to control an NSOutlineView and that class comunicate with my AppDelegate using notification. This class that controls the behavior of the outlineview is initialized using awakefromnib so that header is added immediately (my will), while later by calling a method of this class is populated by children. Everything works ok, but when is the moment to create a notification for my AppleDelegate I discover that instance variable is null while at the time of the initial call was ok.
#interface MyClass : NSObject <NSApplicationDelegate, NSTextViewDelegate, NSTextFieldDelegate, NSOutlineViewDelegate, NSOutlineViewDataSource>
{
NSString * _plistPath;
}
#implementation MyClass
- (void)awakeFromNib {
static dispatch_once_t once;
dispatch_once(& once, ^{
self.Outline.delegate = self;
self.Outline.dataSource = self;
self.Outline.floatsGroupRows = NO;
[_treeController addObject: #{#"title": #"Model list", #"isLeaf": #(NO)}.mutableCopy];
[self.Outline expandItem:[self.Outline itemAtRow:0]];
[self.Outline selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
// Enable Drag and Drop
[self.Outline registerForDraggedTypes: [NSArray arrayWithObject: #"public.text"]];
});
}
- (void)loadPlist:(NSDictionary *)dict path:(NSString *)path
{
_plistPath = path;
NSLog(#"at loadPlist _plistPath = %#, self is = %#", _plistPath, self); // here is ok!
}
// Here all the NSOutlineViewDelegate methods
// .....
// finally after editing value in the interface using the outline view
// and some field attacched to the tree controller..
// I need to notificate AppleDelegate for the changes made to the plist,
//reindicating the path stored in _plistPath variable..but:
- (void)update
{
NSMutableArray *List = [NSMutableArray array];
NSInteger rows = [_Outline numberOfRows];
NSInteger i;
i = 0;
while (i != rows) {
id obj = [_Outline itemAtRow:i];
if (i != 0) {
Tree *entry = (Tree *)(((NSTreeNode *)obj).representedObject);
if (entry.title.length > 0 && ![entry.title isEqualToString:kNullString]
&& entry.size.length > 0 && ![entry.size isEqualToString:kNullString]
&& entry.model.length > 0 && ![entry.model isEqualToString:kNullString]
&& entry.year.length > 0 && ![entry.year isEqualToString:kNullString]) {
NSMutableDictionary *childDict = [NSMutableDictionary dictionary];
[childDict setObject:entry.title forKey:#"Name"];
[childDict setObject:entry.size forKey:#"Size"];
[childDict setObject:entry.model forKey:#"Model"];
[childDict setObject:entry.year forKey:#"Year"];
[List addObject:childDict];
}
}
i++;
}
NSMutableDictionary *uf = [NSMutableDictionary dictionary];
NSLog(#"at update _plistPath = %#, self is = %#", _plistPath, self); // this time here is nil....
[uf setObject:_plistPath forKey:#"path"]; // here crash because _plistPath is nil
[uf setObject:List forKey:#"dictionary"];
NSNotification *note = [NSNotification notificationWithName:#"UpdatePlist" object:_Outline userInfo:uf];
[[NSNotificationCenter defaultCenter] postNotification:note];
}
basically at the second time I need "_plistPath" value is nil (I have some very specific reasons for sending to MyClass the original path and then return it back to the sender (ie AppleDelegate)) and I have more instance variables declared in MyClass that works well..so I can't understand why. Any suggestion?
EDIT
As requested by #matt I change the NSLog including "self"
then the output is that:
2015-05-11 22:06:36.433 TestApp[24990:56140] at loadPlist _plistPath = /Volumes/DATI/test.plist, self is = <MyClass: 0x600000127760>
2015-05-11 22:07:08.552 TestApp[24990:56140] at update _plistPath = (null), self is = <MyClass: 0x608000125c80>
Your log shows the problem:
at loadPlist _plistPath = /Volumes/DATI/test.plist,
self is = <MyClass: 0x600000127760>
at update _plistPath = (null),
self is = <MyClass: 0x608000125c80>
These are two difference instances of MyClass. But plistPath is an instance variable - so it can perfectly reasonably have a value in one instance and be nil in another instance.

How to ask for access to photo library on startup?

I'm building an app that has the user take photos from their library to do things. I'm using X-code, and I had this code under 'didFinishLaunchingWithOptions' but keep getting an 'undeclared identifier' error. What to do?
ALAssetsLibraryGroupsEnumerationResultsBlock assetGroupEnumerator =
^(ALAssetsGroup *assetGroup, BOOL *stop) {
if (assetGroup != nil) {
// do somthing
}
};
ALAssetsLibraryAccessFailureBlock assetFailureBlock = ^(NSError *error) {
LogError(#"Error enumerating photos: %#",[error description]);
};
NSUInteger groupTypes = ALAssetsGroupAll;
[library enumerateGroupsWithTypes:groupTypes usingBlock:assetGroupEnumerator failureBlock:assetFailureBlock];
Too late an answer but you need to define library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
or better use a class method if you are going to reuse the library for more queries
+ (ALAssetsLibrary *)defaultAssetsLibrary
{
static dispatch_once_t pred = 0;
static ALAssetsLibrary *library = nil;
dispatch_once(&pred, ^{
library = [[ALAssetsLibrary alloc] init];
});
return library;
}

NSView Drag Operation Error

I'm coding in Cocoa, on OS X.
I'm trying to receive a file that is dragged and dropped onto my NSView subclass - which I can do; and get its contents and filename and display them - which I can do for any type of file first time, but on the second time, when I try and drag another file on, I can only set the title setTitle:, but not the main body text setText:
The errors I am getting are:
Canceling drag because exception 'NSInternalInconsistencyException' (reason 'Invalid parameter not satisfying: aString != nil') was raised during a dragging session
and
Assertion failure in -[NSTextFieldCell _objectValue:forString:errorDescription:], /SourceCache/AppKit/AppKit-1187/AppKit.subproj/NSCell.m:1532
My code (sorry, it's quite long!):
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
NSURL *file = [NSURL URLFromPasteboard:pboard];
//NSData *data = [NSData dataWithContentsOfURL:file];
NSError *error;
NSStringEncoding encoding;
NSString *contentString = [[NSString alloc] initWithContentsOfURL:file usedEncoding:&encoding error:&error];
NSLog(#"Error: %#",error);
NSString *last = [[file path] lastPathComponent];
NSArray *parts = [last componentsSeparatedByString:#"."];
NSString *filename = [parts objectAtIndex:0];
NSString *fileType = [parts objectAtIndex:1];
NSLog(#"FILETYPE: %#", fileType);
if ([fileType isEqualToString:#"txt"] || [fileType isEqualToString:#"md"]) {
[self setTitle:filename];
if (self.textViewString == (id)[NSNull null] || self.textViewString.length == 0) {
[self setText:contentString];
} else {
BOOL whatToDo = (NSRunCriticalAlertPanel(#"What do you want to do?", nil, #"Append", #"Replace", nil) == NSAlertDefaultReturn);
if (whatToDo) {
//Append
[self setText:[NSString stringWithFormat:#"%#\n%#",self.textViewString,contentString]];
} else {
//Replace
[self setText:contentString];
}
}
return YES;
} else {
return NO;
}
} else if ([[pboard types] containsObject:NSPasteboardTypeString]) {
NSString *draggedString = [pboard stringForType:NSPasteboardTypeString];
if (self.textViewString == (id)[NSNull null] || self.textViewString.length == 0) {
[self setText:draggedString];
} else {
[self setText:[NSString stringWithFormat:#"%#\n%#",self.textViewString,draggedString]];
}
return YES;
}
else {
return NO;
}
}
Thanks in advance! :)
Sounds like Cocoa is canceling the drag when any exception is raised, and an exception is getting raised when something internally is expecting a string and is getting a nil value instead.
It's just a guess without having more information, but I would predict that stringWithFormat: is raising the exception, as it looks like the only really potentially fragile bit of what you have written.
You are doing a couple ill-advised things. First, you are assuming that -initWithContentsOfURL:usedEncoding:error: is succeeding. You should not do this. Instead, you need to pass an NSError ** that can be filled in on error, test whether contentString is nil, and, if so, check the error accordingly. I have a feeling that you will find you are getting nil, and the error will explain why.
Possibly unrelated, but your if (whatToDo) is not doing what you probably think it is. Since whatToDo is a pointer to an autoreleased NSNumber instance your conditional will always evaluate to true, since the pointer is non-zero. What you likely meant to do was something like the following:
BOOL whatToDo = (NSRunCriticalAlertPanel(#"What do you want to do?", nil, #"Append", #"Replace", nil) == NSAlertDefaultReturn);
if (whatToDo) {
//Append
[self setText:[NSString stringWithFormat:#"%#\n%#",self.textViewString,contentString]];
} else {
//Replace
[self setText:contentString];
}
Lots of thanks for the many tips and pieces of advice from this answer by Conrad Shultz! I've followed the advice and tips there.
However, my problem turned out to be very, very basic. It lied in the line BOOL whatToDo = (NSRunCriticalAlertPanel(#"What do you want to do?", nil, #"Append", #"Replace", nil) == NSAlertDefaultReturn);
It turns out a string must be passed to the second parameter, but I was passing nil. Fixed!

can't figure why insert sqlite sql statement is not being executed , Xcode

everything looks good for me, but the prepare_v2 doesn't get SQLITE_OK
the sql instruction is pretty basic, if I copy and paste it on the sqlite manager, it inserts fine
is there anything I am missing?
//from view controller
- (void)viewDidLoad
{
[super viewDidLoad];
DBConnection* dbCon = [DBConnection alloc];
[dbCon init];
[dbCon InsertDataRollNo:#"888"];
}
-(id)init
{
//[super init];
DBName = #"FoodDB2.sqlite";
NSArray* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDir = [documentsPath objectAtIndex:0];
DBPath = [documentsDir stringByAppendingPathComponent:DBName];
return self;
}
-(void)InsertDataRollNo:(NSString*)theName
{
[self CheckAndCreateDB];
sqlite3* database;
if(sqlite3_open([DBPath UTF8String], &database)== SQLITE_OK)
{
NSString* statement;
sqlite3_stmt* compliedStatement;
//statement = [[NSString alloc]initWithFormat:#"insert into Category(TheName)values('%d')",#"epa"];
statement = #"insert into Category(TheName)values('aaa')";
const char* sqlStatement = [statement UTF8String];
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compliedStatement, NULL) == SQLITE_OK)
{
if(SQLITE_DONE!=sqlite3_step(compliedStatement))
{
NSAssert1(0,#"Error by inserting '%s' ", sqlite3_errmsg(database));
}
else
{
NSAssert1(0,#"cool '%s' ", #"ope");
}
}
sqlite3_finalize(compliedStatement);
}
sqlite3_close(database);
}
-(void)CheckAndCreateDB
{
BOOL success;
NSFileManager* fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:DBPath];
if(success) return;
NSString* databasePathFromApp = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:DBName];
[fileManager copyItemAtPath:databasePathFromApp toPath:DBPath error:nil];
//[fileManager release];
}
I figure it out, actually I was not copying the sqlite file to iPhone project, running good now

Removing url fragment from NSURL

I'm writing a Cocoa application, which uses NSURLs -- I need to remove the fragment portion of the URL (the #BLAH part).
example: http://example.com/#blah should end up as http://example.com/
I found some code in WebCore that seems to do it by using CFURL functionality, but it never finds the fragment portion in the URL. I've encapsulated it in a extension category:
-(NSURL *)urlByRemovingComponent:(CFURLComponentType)component {
CFRange fragRg = CFURLGetByteRangeForComponent((CFURLRef)self, component, NULL);
// Check to see if a fragment exists before decomposing the URL.
if (fragRg.location == kCFNotFound)
return self;
UInt8 *urlBytes, buffer[2048];
CFIndex numBytes = CFURLGetBytes((CFURLRef)self, buffer, 2048);
if (numBytes == -1) {
numBytes = CFURLGetBytes((CFURLRef)self, NULL, 0);
urlBytes = (UInt8 *)(malloc(numBytes));
CFURLGetBytes((CFURLRef)self, urlBytes, numBytes);
} else
urlBytes = buffer;
NSURL *result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingUTF8, NULL));
if (!result)
result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingISOLatin1, NULL));
if (urlBytes != buffer) free(urlBytes);
return result ? [result autorelease] : self;
}
-(NSURL *)urlByRemovingFragment {
return [self urlByRemovingComponent:kCFURLComponentFragment];
}
This is used as such:
NSURL *newUrl = [[NSURL URLWithString:#"http://example.com/#blah"] urlByRemovingFragment];
unfortunately, newUrl ends up being "http://example.com/#blah" because the first line in urlByRemovingComponent always returns kCFNotFound
I'm stumped. Is there a better way of going about this?
Working Code, thanks to nall
-(NSURL *)urlByRemovingFragment {
NSString *urlString = [self absoluteString];
// Find that last component in the string from the end to make sure to get the last one
NSRange fragmentRange = [urlString rangeOfString:#"#" options:NSBackwardsSearch];
if (fragmentRange.location != NSNotFound) {
// Chop the fragment.
NSString* newURLString = [urlString substringToIndex:fragmentRange.location];
return [NSURL URLWithString:newURLString];
} else {
return self;
}
}
How about this:
NSString* s = #"http://www.somewhere.org/foo/bar.html/#label";
NSURL* u = [NSURL URLWithString:s];
// Get the last path component from the URL. This doesn't include
// any fragment.
NSString* lastComponent = [u lastPathComponent];
// Find that last component in the string from the end to make sure
// to get the last one
NSRange fragmentRange = [s rangeOfString:lastComponent
options:NSBackwardsSearch];
// Chop the fragment.
NSString* newURLString = [s substringToIndex:fragmentRange.location + fragmentRange.length];
NSLog(#"%#", s);
NSLog(#"%#", newURLString);
This is quite an old question, and it has already been answered, but for another simple option this is how I did it:
NSString* urlAsString = [myURL absoluteString];
NSArray* components = [urlAsString componentsSeparatedByString:#"#"];
NSURL* myURLminusFragment = [NSURL URLWithString: components[0]];
if there is no fragment, urlMinusFragment will be the same as myURL
Swift 3.0
this will remove the fragment
if let fragment = url.fragment{
url = URL(string: url.absoluteString.replacingOccurrences(of: "#\(fragment)", with: "")!
}

Resources