Saving NSMutableArray and loading it in a UITableView - xcode

I want to save multiple NSMutableArray and load it because this array gets it content from a server and i don't want to reload that data every time the app is opened.
First I declared the paths:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *firstPath = [documentsDirectory stringByAppendingPathComponent:#"first"];
NSString *secondPath = [documentsDirectory stringByAppendingPathComponent:#"second"];
NSString *thirdPath = [documentsDirectory stringByAppendingPathComponent:#"third"];
NSString *fourthPath = [documentsDirectory stringByAppendingPathComponent:#"fourth"];
then save the NSMutableArrays:
[firstArray writeToFile:firstPath atomically:YES];
[secondArray writeToFile:secondPath atomically:YES];
[thirdArray writeToFile:thirdPath atomically:YES];
[fourthArray writeToFile: fourthPath atomically:YES];
then open these files in other NSMutableArrays:
firstArrayget = [NSMutableArray arrayWithContentsOfFile:firstPath];
secondArrayget = [NSMutableArray arrayWithContentsOfFile:secondPath];
thirdArrayget = [NSMutableArray arrayWithContentsOfFile:thirdPath];
fourthArrayget = [NSMutableArray arrayWithContentsOfFile:fourthPath];
then I try to load these Arrays (...Arrayget i.e. firstArrayget) into a TableView.
The data gets loaded into the TableView, but when I scroll down the App crashes with the Error:
*** -[CFArray objectAtIndex:]: message sent to deallocated instance 0x930fc80
and in the file:
Thread 1:EXC_BREAKPOINT(code=EXC_1386_BPT,subcode=0x0)
but if I say the TableView to load the data from the (...Array i.e. firstArray),so the data downloaded from the server unsaved.

Assuming you're using MRC and not ARC:
Looks like you're setting an ivar to an autoreleased NSMutableArray.
Try calling retainon the NSMutableArrays, otherwise your NSMutableArrays will just get released and thus deallocated when the autoreleasepool drains.
Another solution is to use a property for each of your NSMutableArrays like this:
// Create a property in your header file
#property (retain) NSMutableArray *firstArrayget;
// And set the property in your method
[self setFirstArrayGet:[NSMutableArray arrayWithContentsOfFile:firstPath]];
You can find more about Objective-C memory management at https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

Related

copy and paste text + image from NSPasteboard

we are working on a C++ Qt applciation that copies selected text and/or images from external applications, modifies it and then paste it back. Since we are on Mac, we are doing this part with Objective-C.
We are having problems trying to get an image from the Pasteboard. It works fine for text, but we are not sure about how to handle images or combination of text+image.
Since we dont know what the user might select, we should be able to perform a generic retrieval of content of the pasteboard to modify it and putting it back in the pasteboard.
We've try this:
//we thought about retrieving some generic item from pasteboard, using NSPasteboardItem
NSArray *classes = [[NSArray alloc] initWithObjects:[NSPasteboardItem class], nil];
NSDictionary *options = [NSDictionary dictionary];
NSArray *auxArray = [[NSPasteboard generalPasteboard] readObjectsForClasses:classes options:options];
NSData *archived_data = [auxArray objectAtIndex:0];
Our solution for handling text was:
NSString *text = [[NSPasteoard generalPasteboard] stringForType:NSStringPboardType];
string text_str = string([text UTF8String]);
It didnt work, so, How can we get the user selection from the pasteboard?
We need to get the raw bytes or rtf content in order to modify it as we need, and then putting it back in the pasteboard and paste it back replacing the original user selection.
Thanks!
I think this function will help you
- (IBAction)paste:sender
{
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
if (ok)
{
NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
NSImage *image = [objectsToPaste objectAtIndex:0];
[imageView setImage:image];
}
}

How can I add and store data in a UITableView?

I'm creating an app that inserts values to a tableview. I also want to add the timestamp on when the value is added to the table. The scenario would be this:
I write some random text in a text field.
I push a button
The text from the text field is saved in the table together with the time I tapped the button.
Done.
(NSString *)dataFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename];
}
(void)applicationWillTerminate:(NSNotification *)notification {
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:field1.text];
[array addObject:field2.text];
[array addObject:field3.text];
[array addObject:field4.text];
[array writeToFile:[self dataFilePath] atomically:YES];
[array release];
}
Depending on how large your data is, you can store it in a plist, or sqlite3.
Here's a link that might be useful:
http://www.bogotobogo.com/XcodeSDK-Chapter10.html

Problems adding data to a plist file

I've been trying to write data back to a pre-defined plist file (data.plist) in my bundle. Using the code below I call the routine 'dictionaryFromPlist' to open the file and then call 'writeDictionaryToPlist' to write to the plist file. However, no data gets added to the plist file.
NSDictionary *dict = [self dictionaryFromPlist];
NSString *key = #"Reports";
NSString *value = #"TestingTesting";
[dict setValue:value forKey:key];
[self writeDictionaryToPlist:dict];
- (NSMutableDictionary*)dictionaryFromPlist {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSMutableDictionary* propertyListValues = [[NSMutableDictionary alloc]
initWithContentsOfFile:filePath];
return [propertyListValues autorelease];
}
- (BOOL)writeDictionaryToPlist:(NSDictionary*)plistDict{
NSString *filePath = #"data.plist";
BOOL result = [plistDict writeToFile:filePath atomically:YES];
return result;
}
The code runs through successfully and no error is thrown but no data is added to my plist file.
You can not write to your bundle, it is read only. If your case though, you are writing to a relative path, not to the bundle.
I'm not sure what the default working directory is for iOS apps. It is best to use absolute paths. You should be writing to the documents/cache directory. Something like this will get the path for you:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Then just grab the lastObject and prepend that to your file name.
As mentioned by #logancautrell you can not write in mainbundle, you can save your plist in the app documents folder, you could do so:
NSString *path = #"example.plist";
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count]> 0)? [paths objectAtIndex: 0]: nil;
NSString *documentPath = [basePath stringByAppendingPathComponent:path] // Documents
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL checkfile = [fileManager fileExistsAtPath: documentPath];
NSLog(#"%#", (checkFile ? #"Exist": #"Not exist"));//check if exist
if(!checkfile) {//if not exist
BOOL copyFileToDoc = [yourDictionary writeToFile:documentPath atomically: YES];
NSLog(#"%#",(copyFileToDoc ? #"Copied": #"Not copied"));
}

Open/edit a .txt file located in application bundle with NSTextView object

I would like to add an NSTextView object to my app and add an action that opens a .txt file located in the app bundle in the textView. Also - I would like to have the option to edit and save the edited doc without renaming it. So standard save, not save as.
What's the best way to handle this?
Use NSString to load the file and put it in your text view:
NSTextView *textView; //your NSTextView object
NSError *err = nil;
NSString *path = [[NSBundle mainBundle] pathForResource:#"EditableFile" ofType:#"txt"];
NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
if(!contents) {
//handle error
}
[textView setString:contents];
Saving is just the opposite. Get the string and write it to the file:
NSTextView *textView; //your NSTextView object
NSError *err = nil;
NSString *path = [[NSBundle mainBundle] pathForResource:#"EditableFile" ofType:#"txt"];
NSString *contents = [textView string];
if(![contents writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&err]) {
//handle error
}

Delete all records in NSManagedObjectContext

Is there a way to delete all the records from an NSManagedObjectContext?
I'm using the following code to insert data:
NSManagedObjectContext * context = [[NSApp delegate] managedObjectContext];
NSManagedObject * basket = nil;
basket = [NSEntityDescription insertNewObjectForEntityForName:#"ShoppingBasket"
inManagedObjectContext: context];
[basket setValue:[firstSelectedObject valueForKey:#"accessoryID"]
forKey: #"accessoryID"];
How do I delete all the records? I want something that's like the "remove:" function, but to remove everything.
To delete all instances of a given entity (we'll use your ShoppingBasket), you can simply fetch all baskets then delete them. It's just a few lines of code:
NSManagedObjectContext * context = [self managedObjectContext];
NSFetchRequest * fetch = [[[NSFetchRequest alloc] init] autorelease];
[fetch setEntity:[NSEntityDescription entityForName:#"ShoppingBasket" inManagedObjectContext:context]];
NSArray * result = [context executeFetchRequest:fetch error:nil];
for (id basket in result)
[context deleteObject:basket];
The alternative in a non-document-based app is to shut down your connection to the data store, delete the actual file, then reconnect (the template code that comes with a standard Core Data project will automatically create the file if it's absent). You then have a brand new, empty store.
Note, the code example ignores any possible error. Don't do that. :-)
A much quicker way would be to just remove store entirely. This way you're not wasting any time fetching objects, or enumerating through them as the other answer does.
NSError *error;
NSURL *applicationDocumentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [applicationDocumentsDirectory URLByAppendingPathComponent:#"MyCDStore.sqlite"];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
Don't forget to re-create it after you have deleted it.

Resources