SQLite iphone data lost when rebooting or closing the app - objective-c

I have a question... I have an application using sqlite to save some data.Everything works perfectly, meaning I can add, delete, view data. The data are persistent when the application goes into background. Now, when I remove the application from memory or reboot the iPhone, the database is corrupted and all the data are messed up !
I have a class call dbAccess where all the database actions are define(add, delete, retreive rows). At the end I have a finalize action, that finalize all the statement used and then close the database.
+ (void)finalizeStatements{
NSLog(#"Finalizing the Delete Statements");
if(deleteStmt) {
NSLog(#"Delete Statement exist... finalization");
sqlite3_finalize(deleteStmt);
deleteStmt = nil;
}
NSLog(#"Finalizing the Add Statements");
if(addStmt) {
NSLog(#"Add Statement exist... finalization");
sqlite3_finalize(addStmt);
addStmt = nil;
}
NSLog(#"Finalizing the Store Statements");
if(storeStmt) {
NSLog(#"Store Statement exist... finalization");
sqlite3_finalize(storeStmt);
storeStmt = nil;
}
NSLog(#"Finalizing the Agent Statements");
if(agentStmt) {
NSLog(#"Agent Statement exist... finalization");
sqlite3_finalize(agentStmt);
agentStmt = nil;
}
NSLog(#"Closing the Database");
if(database) {
NSLog(#"The database exist... closing it");
sqlite3_close(database);
}
}
This method is called by the application delegate when applicationDidEnterBackground and applicationWillTerminate. An openDatabase method is call when applicationDidBecomeActive.
Any ideas why the database is corrupted ?
Thanks.

First off, check out fmdb or some other proven wrappers. You can also browse the code.
Not sure if there's enough info to know why it's corrupt. But, you should get return codes from ALL sqlite3_xxx calls and log at a minimum to understand what's going on or you may just be blasting past an issue.
Also, make sure to call sqlite_errmsg which will offer more clues if the return code is not success.
In my wrapper, I do this in close. It's expected that statements are finalized bu handled if not. I have a statement cache which on clear finalizes each statement.
:
- (void)close
{
if (_sqlite3)
{
NSLog(#"closing");
[self clearStatementCache];
int rc = sqlite3_close(_sqlite3);
NSLog(#"close rc=%d", rc);
if (rc == SQLITE_BUSY)
{
NSLog(#"SQLITE_BUSY: not all statements cleanly finalized");
sqlite3_stmt *stmt;
while ((stmt = sqlite3_next_stmt(_sqlite3, 0x00)) != 0)
{
NSLog(#"finalizing stmt");
sqlite3_finalize(stmt);
}
rc = sqlite3_close(_sqlite3);
}
if (rc != SQLITE_OK)
{
NSLog(#"close not OK. rc=%d", rc);
}
_sqlite3 = NULL;
}
}

Related

How to get file's "Stationary Pad" flag information using objective c

I need to check for "Stationary Pad" flag of a file but I am not getting any way to read this information.
You have to use the Carbon File Manager API to do this, you can't do it from Cocoa. That said, this code does still work in the Xcode 12 beta.
-(BOOL)isStationaryPad:(NSString *)path
{
static kIsStationary = 0x0800;
CFURLRef url;
FSRef fsRef;
FSCatalogInfo catInfo;
BOOL success;
url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, kCFURLPOSIXPathStyle, FALSE);
if (!url) return NO;
success = CFURLGetFSRef(url, &fsRef);
CFRelease(url);
// catalog info from file system reference; isStationary status from catalog info
if (success && (FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, nil, nil, nil))==noErr)
{
return ((((FileInfo*)catInfo.finderInfo)->finderFlags & kIsStationary) == kIsStationary);
}
return NO;
}
This code is from the open source version of the Bean word processor.

How to use URLSession downloadTaskWithResumeData to start download again when AfterdidCompleteWithError Called..?

I have the code to download two files from Server and store It to In local using URLSession (let dataTask = defaultSession.downloadTask(with: url)). Everything Is working fine only the problem is it's downloading first file it's giving me success but the second file is not downloading completely.. So, I hope there is a way to restart download for the second file that gives error ..
I think there is way of doing that and start looking into it and I found this delegate method .. but not much help .. can anyone please help me out how to restart download if it fails .. Do i have to use handleEventsForBackgroundURLSession to clear up previous downloads..?
// bellow download method will triggered when i get filenames I am passing it to this and path is optional here..
func download(path: String?, filenames: [String]) -> Int {
for filename in filenames {
var downloadFrom = "ftp://" + username! + ":"
downloadFrom += password!.addingPercentEncoding(withAllowedCharacters: .urlPasswordAllowed)! + "#" + address!
if let downloadPort = port {
downloadFrom += ":" + String(downloadPort) + "/"
} else {
downloadFrom += "/"
}
if let downloadPath = path {
if !downloadPath.isEmpty {
downloadFrom += downloadPath + "/"
}
}
downloadFrom += filename
if let url = URL(string: downloadFrom) {
let dataTask = defaultSession.downloadTask(with: url)
dataTask.resume()
}
}
return DLResponseCode.success
}
Please find delegate methods bellow ..
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
var responseCode = DLResponseCode.success
// Move the file to a new URL
let fileManager = FileManager.default
let filename = downloadTask.originalRequest?.url?.lastPathComponent
let destUrl = cacheURL.appendingPathComponent(filename!)
do {
let data = try Data(contentsOf: location)
// Delete it if it exists first
if fileManager.fileExists(atPath: destUrl.path) {
do{
try fileManager.removeItem(at: destUrl)
} catch let error {
danLogError("Clearing failed downloadFOTA file failed: \(error)")
responseCode = DLResponseCode.datalogger.failToCreateRequestedProtocolPipe
}
}
try data.write(to: destUrl)
} catch {
danLogError("Issue saving data locally")
responseCode = DLResponseCode.datalogger.noDataConnection
}
// Complete the download message
let message = DLBLEDataloggerChannel.Commands.download(responseCode: responseCode).description
connectionManagerDelegate?.sendMessageToDatalogger(msg: message)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if error == nil {
print("session \(session) download completed")
} else {
print("session \(session) download failed with error \(String(describing: error?.localizedDescription))")
// session.downloadTask(withResumeData: <#T##Data#>)
}
guard error != nil else {
return
}
danLogError("Session \(session) invalid with error \(String(describing: error))\n")
let responseCode = DLResponseCode.datalogger.failToCreateRequestedProtocolPipe
let message = DLBLEDataloggerChannel.Commands.download(responseCode: responseCode).description
connectionManagerDelegate?.sendMessageToDatalogger(msg: message)
}
// When I call didWriteData delegate method it's printing below data seems not dowloaded complete data ..
session <__NSURLSessionLocal: 0x103e37970> download task <__NSCFLocalDownloadTask: 0x108d2ee60>{ taskIdentifier: 2 } { running } wrote an additional 30028 bytes (total 988980 bytes) out of an expected 988980 bytes.
//error that I am getting for second file .. this error is coming some times not always but most of the times..
session <__NSURLSessionLocal: 0x103e37970> download failed with error Optional("cancelled")
Please help me out to figure it out .. If there is any way to handle download again after it fails or why it fails ..
The resume data, if the request is resumable, should be in the NSError object's userInfo dictionary.
Unfortunately, Apple seems to have completely trashed the programming guide for NSURLSession (or at least I can't find it in Google search results), and the replacement content in the reference is missing all of the sections that talk about how to do proper error handling (even the constant that you're looking for is missing), so I'm going to have to describe it all from memory with the help of looking at the headers. Ick.
The key you're looking for is NSURLSessionDownloadTaskResumeData.
If that key is present, its value is a small NSData blob. Store that, then use the Reachability API (with the actual hostname from that request's URL) to decide when to retry the request.
After Reachability tells you that the server is reachable, create a new download task with the resume data and start it.

php-smpp Library not working and fails after two to three SMS

it is very first time i'm messing with sockets , and read many quotes that this is not for newbies.
so problem is i'm using php smpp library for sending SMS which works fine but after delivering two to three SMS delivery fails with following warning
Warning: stream_socket_sendto() [function.stream-socket-sendto]: An existing connection was forcibly closed by the remote host', and to make it work again i need to restart` apache.
Following is write function which throwing exception
public function write($buf) {
$null = null;
$write = array($this->handle_);
// keep writing until all the data has been written
while (strlen($buf) > 0) {
// wait for stream to become available for writing
$writable = #stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
if ($writable > 0) {
// write buffer to stream
$written = stream_socket_sendto($this->handle_, $buf);
if ($written === -1 || $written === false) {
throw new TTransportException('TSocket: Could not write '.$written.' bytes '.
$this->host_.':'.$this->port_);
}
// determine how much of the buffer is left to write
$buf = substr($buf, $written);
} else if ($writable === 0) {
throw new TTransportException('TSocket: timed out writing '.strlen($buf).' bytes from '.
$this->host_.':'.$this->port_);
} else {
throw new TTransportException('TSocket: Could not write '.strlen($buf).' bytes '.
$this->host_.':'.$this->port_);
}
}
}
Please anyone can put some light
It was the bug which i won't able to identify/ rectify. then i used an other library from http://www.codeforge.com/read/171085/smpp.php__html and it really saved me.

Variable return runtime error

I am making an iPhone app with cocos2d and Everytime I try to return a variable from a function I get a run time error on the code below...
GB2ShapeCache *cache = [GB2ShapeCache sharedShapeCache];
//EXC_BAD_ACCESS run time error here
*eggFixture = [cache addFixturesToBody:body forShapeName:#"egg3"];
I don't know what I am doing wrong... here is the code for addFixturesToBody...
-(b2Fixture) addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape
{
BodyDef *so = [shapeObjects objectForKey:shape];
assert(so);
b2Fixture *Fixi;
FixtureDef *fix = so->fixtures;
while(fix)
{
Fixi = body->CreateFixture(&fix->fixture);
fix = fix->next;
}
return *Fixi;
}
and here I define my variable eggFixture
b2Fixture *eggFixture;
and here is where I try to use the b2fixture eggFixture later
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if ((contact.fixtureA == locations.platformFixture && contact.fixtureB == eggFixture) ||
(contact.fixtureA == eggFixture && contact.fixtureB == locations.platformFixture)) {
NSLog(#"Ball hit bottom!");
}
}
Any help? thankyou :)
Looks like body is nil. It will certainly crash here when body is nil:
Fixi = body->CreateFixture(&fix->fixture);
This article has some tips for debugging issues like EXC_BAD_ACCESS.

Not able to update firefox sqlite database when firefox is running-MacOS

I have the following code snippet to update firefox extension sqlite data base
NSString * profileFolderPath = [[ #"~" stringByExpandingTildeInPath] stringByAppendingPathComponent:#"/Library/Application Support/Firefox/Profiles"];
NSString *sqlitePath = [pathToProfileFolder stringByAppendingPathComponent:#"extensions.sqlite"];
int rc = sqlite3_open([sqlitePath UTF8String], &db);
if( rc )
{
NSLog(#"enable extension :%#\n",[NSString stringWithCString:sqlite3_errmsg(db)]);
sqlite3_close(db);
return NO;
}
else {
NSLog(#"opened entensions db successfully \n");
}
// check the values for active and userDisabled fields
rc = sqlite3_exec(db,"SELECT active,userDisabled FROM addon where id='myId.com'",sqliteCallback,0,&zErrMsg);
if (rc!=SQLITE_OK ) {
NSLog(#"error quering the entensions database :%#\n",[NSString stringWithCString:zErrMsg]);
if(zErrMsg)
sqlite3_free(zErrMsg);
sqlite3_close(db);
return NO;
// handle error
}
When firefox application is not in running state,I can read the values and also update the database,but when the firefox is running I am not able to read the values from the database as sqlite3_exec statement is returning the value 5 and I can see the error in console saying "error quering the extensions database :database is locked".
How can I resolve this issue.Please help.
You cannot b/c firefox keeps its own config file (and extensions db file IS a firefox own config file) open while it runs.