How to use method MR_fetchAllSortedBy in background thread?
I tried so:
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadFetchedResultsController];
}
- (void)loadFetchedResultsController
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
_fetchedResultsController = [Podcast MR_fetchAllSortedBy:#"position"
ascending:YES
withPredicate:nil
groupBy:nil
delegate:self]
dispatch_async(dispatch_get_main_queue(),^{
if (![self.fetchedResultsController performFetch:&error])
{
[MagicalRecord handleErrors:error];
}
});
});
}
These seem loaded, but the UITableView is empty
Related
I have several CoreDataTableViewControllers that utilize the helper class from Paul Hegarty's course. Everyone of them works except this one, and I cannot see a difference.
When the table first comes up, it is correctly populated and the segue executes properly when a cell is selected. However when I hit the back button, the table displays (null), (null) everywhere.
I have tried every variant of calling [self useDocument] that I can think of, still to no avail. Any thoughts? Thanks in advance.
//
// TeamTableViewController.m
//
#import "TeamTableViewController.h"
#import "iTrackAppDelegate.h"
#import "CoreDataTableViewController.h"
#import "SchoolRecords.h"
#import "ScheduleViewController.h"
#interface TeamTableViewController ()
#property NSInteger toggle;
#end
#implementation TeamTableViewController
#synthesize iTrackContext = _iTrackContext;
#synthesize schoolSelected = _schoolSelected;
-(void) setSchoolSelected:(SchoolRecords *)schoolSelected
{
_schoolSelected = schoolSelected;
}
-(void) setITrackContext:(NSManagedObjectContext *)iTrackContext
{
if(_iTrackContext != iTrackContext){
if (!iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
_iTrackContext = cdh.context;
} else {
_iTrackContext = iTrackContext;
}
}
[self useDocument];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"SchoolRecords"];
// no predicate because we want ALL the Athletes
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"schoolName" ascending:YES],
nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.iTrackContext
sectionNameKeyPath:nil
cacheName:nil];
__block NSInteger myCount;
int64_t delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.iTrackContext performBlock:^(void){NSError* requestError = nil;
myCount = [self.iTrackContext countForFetchRequest:request error:&requestError];
NSLog(#"In %# and count of iTrackContext = %lu", NSStringFromClass([self class]),(unsigned long)myCount);
}];
if (!myCount || myCount == 0) {
[self displayAlertBoxWithTitle:#"No Teams" message:#"Have you added athletes yet? \nPlease go to Add Athletes" cancelButton:#"Okay"];
}
});
}
- (void)useDocument
{
if (self.iTrackContext) {
[self setupFetchedResultsController];
} else {
NSString* errorText = #"A problem arose opening the search results database of Athletes.";
[self displayAlertBoxWithTitle:#"File Error" message:errorText cancelButton:#"Okay"];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
[self setITrackContext:cdh.context];
} else {
NSLog(#"In %# of %#. Getting ready to call useDocument",NSStringFromSelector(_cmd), self.class);
[self useDocument];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// If divide into sections use line below otherwise return 1.
// return [[self.fetchedResultsController sections] count];
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Do not really need this with only one section, but makes code usable if add sections later.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"teamInformation";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
SchoolRecords *schoolResults = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* titleText = schoolResults.schoolName;
cell.textLabel.text = titleText;
cell.detailTextLabel.text = [NSMutableString stringWithFormat:#"%#, %#", schoolResults.schoolCity, schoolResults.schoolState];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
# pragma navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
[self setSchoolSelected:[self.fetchedResultsController objectAtIndexPath:indexPath]];
// be somewhat generic here (slightly advanced usage)
// we'll segue to ANY view controller that has a photographer #property
if ([segue.identifier isEqualToString:#"scheduleDetailSegue"]) {
// use performSelector:withObject: to send without compiler checking
// (which is acceptable here because we used introspection to be sure this is okay)
NSLog(#"Preparing to passing school with schoolID = %#", self.schoolSelected.schoolID);
[segue.destinationViewController convenienceMethodForSettingSchool:self.schoolSelected];
}
}
- (void) displayAlertBoxWithTitle:(NSString*)title message:(NSString*) myMessage cancelButton:(NSString*) cancelText
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:myMessage
delegate:nil
cancelButtonTitle:cancelText
otherButtonTitles:nil];
[alert show];
}
#end
Well, I am not certain what the problem was. I ended up deleting the "offending" TableViewControllers in StoryBoard and recreated them. That did the trick. In retrospect, I wonder if I did not specify the wrong type of segue from my tabViewController. But I deleted it before I thought of that possibility.
I have a MainController and detailedcontroller. When I popover the Book selection and select a Book, the detailcontroller display an UIWebView with the book articles :
#interface IpadBooksViewController : UITableViewController {
SearchResult *searchResult;
IpadArticleViewController *detailController;
IpadMainViewController *mainController;
UIPopoverController *popover;
}
Into the UIWebView, I display an Email icon and catch the scheme :
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = [request URL];
NSString *scheme = [url scheme];
NSString *host = [url host];
if ([[url description] hasSuffix:#"next"]) {
NSLog(#"next Show");
}
BOOL isShareLinks = [host isEqualToString:#"displayShareLinks"];
BOOL isFavoriteLinks = [host isEqualToString:#"displayFavoriteLinks"];
if ([#"myappurl" isEqualToString:scheme] && (isShareLinks || isFavoriteLinks)) {
self.selectedArticleNumber = [url.path lastPathComponent];
if (isShareLinks) {
[self sendMailArticleNumber:selectedArticleNumber];
} else if (isFavoriteLinks) {
NSLog(#"ipad favorite clicked");
[self toggleFavorite:selectedArticleNumber];
Broker *broker = [[Broker alloc] init];
[broker loadProjects:self];
[broker release];
}
}
return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}
Action is supposed to display the MFMailController under my UIWebView, but nothing is displayed without error message :
- (void) sendMailArticleNumber:(NSString *)articleNumber {
MFMailComposeViewController* composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:#"Article"];
NSString *messageBody = [Article fetchBody:articleNumber bookId:bookId];
[composer setMessageBody:messageBody isHTML:YES];
[self presentModalViewController:composer animated:YES];
[composer release];
}
Any help will be welcomed. I did try creating a popover, addView atIndex without success ... Let me know if you need more code.
David
I did solve the issue by loading the controller into the delegate as following :
[((PublilexAppDelegate*)[[UIApplication sharedApplication] delegate]) sendMailArticleNumber:selectedArticleNumber bookId:self.bookId];
And then into the Delegate :
- (void) sendMailArticleNumber:(NSString *)articleNumber bookId:(NSString*)bookId {
MFMailComposeViewController* composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:#"Article"];
NSString *messageBody = [Article fetchBody:articleNumber bookId:bookId];
[composer setMessageBody:messageBody isHTML:YES];
[self->navigationController presentModalViewController:composer animated:YES];
[composer release];
}
And to dismiss and comeback to the previous view :
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self->navigationController dismissModalViewControllerAnimated:YES];
// [self dismissViewControllerAnimated:YES completion:nil];
// [((PublilexAppDelegate*)[[UIApplication sharedApplication] delegate]) navigateToIpadMain];
}
I am working on my first iCloud App. After working for a while the app cannot access a UIManagedDocument any more due to an "UIDocumentStateSavingError". Is there any way to actually find out what error occurred?
This is my code to create the UIManagedDocument:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
iCloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (iCloudURL == nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self iCloudNotAvailable];
});
return;
}
iCloudDocumentsURL = [iCloudURL URLByAppendingPathComponent:#"Documents"];
iCloudCoreDataLogFilesURL = [iCloudURL URLByAppendingPathComponent:#"TransactionLogs"];
NSURL *url = [iCloudDocumentsURL URLByAppendingPathComponent:#"CloudDatabase"];
iCloudDatabaseDocument = [[UIManagedDocument alloc] initWithFileURL:url];
NSMutableDictionary *options = [NSMutableDictionary dictionary];
NSString *name = [iCloudDatabaseDocument.fileURL lastPathComponent];
[options setObject:name forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudCoreDataLogFilesURL forKey:NSPersistentStoreUbiquitousContentURLKey];
iCloudDatabaseDocument.persistentStoreOptions = options;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(documentContentsChanged:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:iCloudDatabaseDocument.managedObjectContext.persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(documentStateChanged:) name:UIDocumentStateChangedNotification object:iCloudDatabaseDocument];
if ([[NSFileManager defaultManager] fileExistsAtPath:[iCloudDatabaseDocument.fileURL path]]) {
// This is true, the document exists.
if (iCloudDatabaseDocument.documentState == UIDocumentStateClosed) {
[iCloudDatabaseDocument openWithCompletionHandler:^(BOOL success) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[self documentConnectionIsReady];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self connectionError:iCloudConnectionErrorFailedToOpen];
});
}
}];
} else if (iCloudDatabaseDocument.documentState == UIDocumentStateNormal) {
...
}
} else {
...
}
});
The Document already exists and thus openWithCompletionHandler: is called on the document. This fails and the UIDocumentStateChangedNotification is fired which shows a document states of 5:
UIDocumentStateClosed and
UIDocumentStateSavingError
After this the completion block gets called. What is correct way to proceed from here? Is there any way to find out what went wrong and what kind of error occurred?
I tried to re-open the document in the completion block but the result is the same.
I guess I could solve the problem by just deleting the file and recreate it. But this is obviously not an option once the app will be out in the store. I would like to know what is going wrong and give the user an appropriator way to handle the problem.
I already checked other questions here handling the UIDocumentStateSavingError (there a not a lot of them) but the seem not to be applicable for the problem here.
Any idea how I can find out what the problem is? I cannot belive that the API tells you "Something went wrong during saving but I will not tell you what!"
You can query the documentState in the completion handler. Unfortunately, if you want the exact error, the only way to get it is to subclass and override handleError:userInteractionPermitted:
Maybe something like this would help (typed freehand without compiler)...
#interface MyManagedDocument : UIManagedDocument
- (void)handleError:(NSError *)error
userInteractionPermitted:(BOOL)userInteractionPermitted;
#property (nonatomic, strong) NSError *lastError;
#end
#implementation MyManagedDocument
#synthesize lastError = _lastError;
- (void)handleError:(NSError *)error
userInteractionPermitted:(BOOL)userInteractionPermitted
{
self.lastError = error;
[super handleError:error
userInteractionPermitted:userInteractionPermitted];
}
#end
Then in you can create it like this...
iCloudDatabaseDocument = [[UIManagedDocument alloc] initWithFileURL:url];
and use it in the completion handler like this...
[iCloudDatabaseDocument openWithCompletionHandler:^(BOOL success) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[self documentConnectionIsReady];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self connectionError:iCloudConnectionErrorFailedToOpen
withError:iCloudDatabaseDocument.lastError];
});
}
}];
Based on #JodyHagins excellent snippet, I have made a UIDocument subclass.
#interface SSDocument : UIDocument
- (void)openWithSuccess:(void (^)())successBlock
failureBlock:(void (^)(NSError *error))failureBlock;
#end
#interface SSDocument ()
#property (nonatomic, strong) NSError *lastError;
#end
#implementation SSDocument
- (void)handleError:(NSError *)error userInteractionPermitted:(BOOL)userInteractionPermitted {
self.lastError = error;
[super handleError:error userInteractionPermitted:userInteractionPermitted];
}
- (void)clearLastError {
self.lastError = nil;
}
- (void)openWithSuccess:(void (^)())successBlock failureBlock:(void (^)(NSError *error))failureBlock {
NSParameterAssert(successBlock);
NSParameterAssert(failureBlock);
[self clearLastError];
[self openWithCompletionHandler:^(BOOL success) {
if (success) {
successBlock();
} else {
NSError *error = self.lastError;
[self clearLastError];
failureBlock(error);
}
}];
}
#end
i want to show leaderbord in my own game ....i am using following method for that but noting happen ... i am confuse with rootview controller as my game is developed in cocos2d so there is nothing like dat :(
// Leaderboards
-(void) showLeaderboard
{
if (isGameCenterAvailable == NO)
return;
GKLeaderboardViewController* leaderboardVC = [[[GKLeaderboardViewController alloc] init] autorelease];
if (leaderboardVC != nil)
{
leaderboardVC.leaderboardDelegate = self;
[self presentViewController:leaderboardVC];
}
}
///
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController*)viewController
{
[self dismissModalViewController];
[delegate onLeaderboardViewDismissed];
}
///////
-(UIViewController*) getRootViewController
{
return [UIApplication sharedApplication].keyWindow.rootViewController;
}
///
-(void) presentViewController:(UIViewController*)vc
{
UIViewController* rootVC = [self getRootViewController];
[rootVC presentModalViewController:vc animated:YES];
}
////
-(void) dismissModalViewController
{
UIViewController* rootVC = [self getRootViewController];
[rootVC dismissModalViewControllerAnimated:YES];
}
...
regards
Haseeb
i dont know but it work for me.if anyone can describe the real reason for why this working in this way i will be very glad....i call it through appdelegate
[(myAppDelegate*)[[UIApplication sharedApplication] delegate]gameCenter];
and from appdelegate i call rootviewcontroller method like
-(void)gameCenter
{
[rootViewController gameCenterLeaderboard];
}
and in rootviewcontroller there is a method
-(void)gameCenterLeaderboard
{
GKLeaderboardViewController* leaderboardVC = [[[GKLeaderboardViewController alloc] init] autorelease];
if (leaderboardVC != nil) {
leaderboardVC.leaderboardDelegate = self;
[self presentModalViewController: leaderboardVC animated: YES];
}
}
the following method is also override in rootviewcontroller
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)leaderboardController
{
[self dismissModalViewControllerAnimated:YES];
}
If you don't have a root UIViewController then I'd recommend creating a new UIViewController set it's view to your openGLView then use that view controller to present the leaderboard as a modal view controller.
UIViewController *leaderboardViewController = [[UIViewController alloc] init];
[leaderboardViewController setView:[[CCDirector sharedDirector] openGLView]];
[leaderboardViewController presentModalViewController:leaderboardVC animated:YES]; //leaderboardVC is your GKLeaderboardViewController
I want to add simple search bar in the table view. Program getting run with no error, but when I try to add text in search bar, program gets terminates
following is my code:
#interface RootViewController : UITableViewController<UISearchBarDelegate> {
NSArray *list;
IBOutlet UISearchBar *searchBar;
NSMutableArray *searchresult;
BOOL isSearchon;
BOOL canSelectRow;
}
#property(nonatomic, retain)NSArray *list;
#property(nonatomic, retain)IBOutlet UISearchBar *searchBar;
-(void)doneSearching:(id)sender;
-(void)searchlist;
#end
//in .m
#implementation RootViewController
#synthesize list,searchBar;
-(void)doneSearching:(id)sender
{
isSearchon=NO;
canSelectRow=YES;
self.tableView.scrollEnabled=YES;
self.navigationItem.rightBarButtonItem=nil;
[searchBar resignFirstResponder];
[self.tableView reloadData];
}
-(void)searchlist
{NSString *searchText = searchBar.text;
[searchresult removeAllObjects];
for(NSString *str in list)
{
NSRange titleResultsRange=[str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[searchresult addObject:str];
}
}
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
[self searchlist];
}
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
if([searchText length]>0)
{isSearchon =YES;
canSelectRow=YES;
self.tableView.scrollEnabled=YES;
[self searchlist];}
else{
isSearchon =NO;
canSelectRow=NO;
self.tableView.scrollEnabled=NO;
}
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
list = [[NSArray alloc]initWithObjects:#"rohan",#"vidhya",#"kavita",#"pushkar",nil];
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType=UITextAutocorrectionTypeYes;
searchresult=[[NSMutableArray alloc]init];
isSearchon =NO;
canSelectRow=YES;
self.navigationItem.title = #"Names";
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
isSearchon =YES;
canSelectRow=NO;
self.tableView.scrollEnabled=NO;
self.navigationItem.rightBarButtonItem=[[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneSearching:)]autorelease];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(isSearchon){
return [searchresult count];}
else{
return [list count];}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if(isSearchon)
{
cell.text=[searchresult objectAtIndex:indexPath.row];}
else{
cell.text=[list objectAtIndex:indexPath.row];}
// Configure the cell.
return cell;
}
- (void)dealloc {
[super dealloc];
[searchBar release];
}
#end
I have edited my code in my question...it works fine nw....AnyOne willing to use searchbar in tableview in Iphones can refer the code.