Sort List Based On Custom User Settings - iphone

I'm working on an app where a user can upload and download information. The information is downloaded in such a way that when it's downloaded, it's ordered according to when it was submitted.
What I'd like is for the user to be able to reorganize the table view, save the order to a preference file (all ready working) and from now on, whenever data is request, the order now conforms to the users re-organized list.
Maybe my brains just fried, but is there an array function that can accomplish this, or am I on my own? Any suggestions how to go about writing something like this?
Thanks

What about NSSortDescriptor:
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:
[[[NSSortDescriptor alloc] initWithKey:#"keyToBeSorted"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease]]];

Related

Using NSUserDefaults to load data depending on which table view cell is pressed

I want my app to work just like the 'contacts' app on iOS. When a user selects a certain TableViewCell, i want to load certain data.
No Matter which cell is pressed, Either "Joseph, Richard, or Shannon", This view comes up:
Both of the views look the exact same, but they just display different information. So i guess my question is: How can I programmatically set a key #"cell1" #"cell2", etc... for each cell using NSUserDefaults? But here is the catch, I dont know how many cells will be added, so i cant hard code this, How can I create a key for each table view cell for how ever many is added? Thanks for the help!
If you have your heart stuck on using NSUserDefaults, try this:
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
cellNumber = [prefs objectForKey:[NSString stringWithFormat:#"cell%d", index]];
You can then save the max index so that you know exactly how many UITableViewCells you will have to display.
Keep in ming that there is a low storage limit for NSUserDefaults, so you may not be able to store all of your information there. You can find out more details here.
Hope that Helps!
Perhaps you don't want to use NSUserDefaults.... that's only used for persistant user information, such as preferences. It'd be better to use Core Data for that sort of thing.
One idea, since you want to tag the views, is to use the -[UIView setTag:] or UIView.tag property/method on the UITableViewCell during cell dequeueing. Using the UITableView delegate methods, you could detect a tap on the cell, retrieve its tag, and look up the NSUserDefaults, or better, your database.
The preferred way, is to keep an indexed database, dequeue a cell, and when it's tapped, navigate to the detail pane using the cell's index. This is a far more representative programming model, than tagging a view and using NSUserDefaults to pull the data.
You can do that by creating an NSMutableDictionary which stores key/value pairs for each cell than storing it in NSUserDefaults
NSMutableDictionay *dict = [[NSMutableDictionary alloc] init];
[[NSUserDefaults standardUserDefaults] setObject:dict forKey:#"myKey"];
[dict release];
than you can update the dictionary with cell values whenever you want:
NSMutableDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:#"myKey"];
[dict setValue:aNameforThisCell forKey:[NSString stringWithFormat#"cell%d", indexPath.row]];

No service names in UIActivityViewController

I'm trying to use UIActivityViewController to share an image from my app. This is the source code:
UIImage *sourceImage = [[UIImage alloc] initWithContentsOfFile:[[self currentMedia] path]];
NSArray *activityItems = #[sourceImage];
UIActivityViewController *avc = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
avc.excludedActivityTypes = [NSArray arrayWithObjects:UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, nil];
[self presentViewController:avc animated:YES completion:nil];
[avc release];
[sourceImage release];
Everything works fine except for one issue: I don't see service names (Email, Twitter, Facebook etc) in the service picker. Look at the screenshot below:
Am I doing something wrong?
I am using ARC and don't have such problem. As far as UIActivityViewController is hardly rely on multithreading and blocks it is possible to affect some objects lifetime. So I would try to switch to ARC as recommends Apple or at least to make retained class property for UIActivityViewController.
If you pass nil for the activity types and you specify excluded types, nothing will show up.
However if you just pass nil for the first parameter, all the available built-in service types will show up.
I'm still having a bit of trouble getting this API to behave as I want it to, but that's one thing I did find.
You can use UIActivity class for this purpose. Activity objects are used in conjunction with a UIActivityViewController object, which is responsible for presenting services to the user.
look into activityTitle method of UIActivity class it returns string that describes the service.
Here is Example project.
Hope it helps you.

CoreData save/revert unsaved changes

I have a list of objects in a UITableView, managed by a NSFetchedResultsController. When the user selects an object, an edit view is displayed, allowing the user to edit the selected NSManagedObject instance. The properties of the object are updated in the object as the user makes changes.
The thing is, there is, as usual, a Save button and a Cancel button. If the user taps save, the NSManagedObjectContext is saved, and the change is reflected. However, if the user taps cancel, I need the object to revert to the state it was in before. Calling [managedObjectContext rollback] doesn't work for this purpose.
Does anyone know how to properly implement this? I can not store the object's properties as temporary separate ivars during editing, because there are multiple objects that could be edited, all of which have different properties.
Update
What I'm currently doing is storing the NSManagedObject in an instance variable, and calling save: to save and rollback to cancel. Instance variables are modified using either object.property = something or [object setValue:something forKey:#"property"]. This does not work as expected, instead producing this behaviour:
If you edit and save, changes update as expected. However, if you edit again, and cancel without making changes, the state of the object reverts back as it was before the save.
If you edit and cancel, the changes are still updated, as if saved. Editing and cancelling again (without making changes) will revert it back to the state it was in before.
Also:
Could this have anything to do with the way I initialise the NSFetchedResultsController that is used to populate the table view? Code:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSString *entityName = self.entityName;
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[fetchRequest setIncludesPendingChanges:NO];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
Look http://www.section42.de/coredata-how-to-revert-a-managed-object-to-its-original-state. This will help you for sure.
You need to make sure you're setting an NSUndoManager instance on your managed object context as it is nil by default on iOS. Related solution here:
https://stackoverflow.com/a/2214982/318456
Having given up on all the mechanisms in place in CoreData to do this (none of them worked), I ended up storing all the properties of the object as separate variables in the edit view controller, and rolling back to them on cancel.
I had the same problem. It happened because the textField was in modification process when user click back. If user click done on keyboard before click back then everything works fine.
I would store the NSManagedObject as a property of the edit view controller. Then you can edit all of its properties, and either save or rollback when dismissing the view.

Getting the most played track out of the iPod library (MPMediaQuery)

I need to get out the 25 most Played Songs out from my iPod Library with my iPhone app. i am using a MPMediaQuery.
One solutions would be to loop through all tracks and them comparing by MPMediaItemPropertyAlbumTrackCount. But i think thats a bit unefficient. Is there a way to directly get the Most Played items playlist?
I think you are looking for MPMediaItemPropertyPlayCount not MPMediaItemPropertyAlbumTrackCount. MPMediaItemPropertyAlbumTrackCount is the track number of the song as it appears in its album.
MPMediaItemPropertyPlayCount unfortunately cannot be used for making queries with MPMediaQuery since it is a user-defined property.
Your best option is to store all the play counts in a database like Core Data when your app is opened for the first time and update it by registering for notifications when the user's library changes.
you can use NSSortDescriptor to sort the most played songs
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:MPMediaItemPropertyPlayCount ascending:NO];
NSArray *sortedSongsArray = [[everything items] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];

Creating a plist file programmatically

this question is regarding xcode objective c and iphone development:
So I want to store an array in a new plist file and I know how to retrieve the file path and write the data into the file (at least I think I do) and all that jazz once the plist is created, but how do I actually create the plist file the first time the app is run or the first time I go to enter data into it? I want it to live in the documents folder of my app.
I'm assuming this is pretty simple I just can't seem to find documentation on it.
I ended up using NSKeyedValue there was a great tutorial here:
http://vimeo.com/1454094
I know technically this is not the answer to the question but it did solve my problem.
To save:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array writeToFile:[#"/path/to/file.plist"] atomically: TRUE];
To retrieve:
NSMutableArray *array = [[NSMutableArray arrayWithContentsOfFile:[#"/path/to/file.plist"]] retain];
[myArray writeToFile:aFile atomically:YES];