I have a problem on my objective-C iOS App.
I have a UItableview with multiple row defined with data loaded from my backend URL
This table view is a Job Table. let say that on my backend I have 3 row for this job table (photographer, architect and teacher). If i add a new job (baker), it is correctly download on the tableview when I restart my App (so 4 row on the App).
Now when I am deleting a job on my backend, the job is not deleted from the table on my iPhone. It's causing me trouble as users selecting the deleted job row are facing a crash or an error ... to remove it I have to delete the App and reload it (which is a real mess)
What would you recommend me ?
Many many thanks for your help,
Best, David
// JobsVC.m
#import "JobsVC.h"
#import "DataProvider.h"
#import "JobsTableViewCell.h"
#import "DBJobs.h"
#import "DBLinkUserJob.h"
#import <MagicalRecord/MagicalRecord.h>
#interface JobsVC ()
#property (weak, nonatomic) IBOutlet UITableView *jobsTableView;
#property (weak, nonatomic) IBOutlet UIButton *okButton;
#property (weak, nonatomic) IBOutlet UIView *selectJobsView;
#property (weak, nonatomic) IBOutlet UILabel *selectJobsTitleLabel;
#property (weak, nonatomic) IBOutlet UILabel *selectJobsDetailsLabel;
#property (strong, nonatomic) NSMutableDictionary *jobsDataSource;
#property (strong, nonatomic) NSMutableArray *selectedJobs;
#property (nonatomic, strong) UIRefreshControl *refreshControl;
#property (strong, nonatomic) NSMutableArray *jobsArray;
#end
#implementation JobsVC
- (void)viewDidLoad {
[super viewDidLoad];
self.selectedJobs = [NSMutableArray new];
self.jobsDataSource = [NSMutableDictionary new];
self.jobsArray = [NSMutableArray new];
self.verifiedHyperjobs = [NSMutableArray new];
[self initialSetup];
[self loadJobs];
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshData) forControlEvents:UIControlEventValueChanged];
[self.jobsTableView addSubview:self.refreshControl];
}
-(void)viewWillAppear:(BOOL)animated{
//Editing header view according to selection mode
if (self.jobsMode == Jobs_Mode_Lb || self.jobsMode == Jobs_Mode_Ad) {
[self.selectJobsView setFrame:CGRectMake(self.selectJobsView.frame.origin.x, self.selectJobsView.frame.origin.x, self.selectJobsView.frame.size.width, 60.0)];
[self.selectJobsTitleLabel setFrame:CGRectMake(self.selectJobsTitleLabel.frame.origin.x, 19.0, self.selectJobsTitleLabel.frame.size.width, 0.0)];
[self.selectJobsDetailsLabel setFrame:CGRectMake(self.selectJobsDetailsLabel.frame.origin.x, 19.0, self.selectJobsDetailsLabel.frame.size.width, 36.0)];
[self.selectJobsTitleLabel setText:#""];
[self.selectJobsDetailsLabel setText:NSLocalizedString(#"jobs_select_ad_lb_jobs", nil)];
[self.selectJobsDetailsLabel setFont:[UIFont fontWithName:#"DIN Alternate" size:18]];
[self.selectJobsDetailsLabel setMinimumScaleFactor:0.6];
}
else{
[self.selectJobsView setFrame:CGRectMake(self.selectJobsView.frame.origin.x, self.selectJobsView.frame.origin.x, self.selectJobsView.frame.size.width, 180.0)];
[self.selectJobsTitleLabel setFrame:CGRectMake(self.selectJobsTitleLabel.frame.origin.x, 19.0, self.selectJobsTitleLabel.frame.size.width, 36.0)];
[self.selectJobsDetailsLabel setFrame:CGRectMake(self.selectJobsDetailsLabel.frame.origin.x, 63.0, self.selectJobsDetailsLabel.frame.size.width, 117.0)];
[self.selectJobsTitleLabel setText:NSLocalizedString(#"jobs_select_title", nil)];
[self.selectJobsTitleLabel setFont:[UIFont fontWithName:#"AWConquerorDidot-Light" size:24]];
[self.selectJobsTitleLabel setMinimumScaleFactor:0.6];
[self.selectJobsDetailsLabel setText:NSLocalizedString(#"jobs_select_details", nil)];
[self.selectJobsDetailsLabel setFont:[UIFont fontWithName:#"DIN Alternate" size:18]];
[self.selectJobsDetailsLabel setMinimumScaleFactor:0.6];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Helpers
- (void)initialSetup {
[self setupNavigationBar:YES];
if (self.jobsMode == Jobs_Mode_Lb || self.jobsMode == Jobs_Mode_Ad || ![LogicManager sharedInstance].currentUserID) {
[self.navigationItem setTitle:NSLocalizedString(#"jobs_ttl", nil)];
} else {
DBUsers *userDB = [DBUsers MR_findFirstByAttribute:#"userID" withValue:[LogicManager sharedInstance].currentUserID];
[self.navigationItem setTitle:userDB.login];
}
[self.navigationController.navigationBar
setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor],
NSFontAttributeName : [UIFont fontWithName:#"AWConquerorDidot-Light" size:24]}];
[self.okButton setTitle:NSLocalizedString(#"button_ok", nil) forState:UIControlStateNormal];
[self.okButton.titleLabel setFont:[UIFont fontWithName:#"DIN Alternate" size:16]];
}
#pragma mark - Logic
- (void)loadJobs {
[self.jobsDataSource removeAllObjects];
[self.jobsArray removeAllObjects];
if (!self.selectedJobs.count) {
if (self.jobsMode == Jobs_Mode_Lb) {
self.selectedJobs = [DataProvider sharedInstance].lbJobsArray;
} else if (self.jobsMode == Jobs_Mode_Ad) {
self.selectedJobs = [DataProvider sharedInstance].adJobsArray;
} else {
self.selectedJobs = [DataProvider sharedInstance].userJobsArray;
}
}
// NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(isM == NO)"];
// NSMutableArray *sources = [[DBJobs MR_findAllWithPredicate:predicate] mutableCopy];
// NSMutableArray *sources = [[DBJobs MR_findAll] mutableCopy];
NSMutableArray* sources = [[[[DBJobs MR_findAll] mutableCopy] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
if([[LogicManager sharedInstance].deviceLanguage containsString:#"fr"]){
return [NSLocalizedString([(DBJobs*)a name_fr],nil) caseInsensitiveCompare:NSLocalizedString([(DBJobs*)b name_fr],nil)];
}
else{
return [NSLocalizedString([(DBJobs*)a name],nil) caseInsensitiveCompare:NSLocalizedString([(DBJobs*)b name],nil)];
}
}] mutableCopy];
for (DBJobs *jobDB in sources) {
NSString *jobName = [[LogicManager sharedInstance].deviceLanguage containsString:#"fr"] ? jobDB.name_fr : jobDB.name;
NSString *jobIndex = [[jobName substringToIndex:1] uppercaseString];
if (![[[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)] containsObject:jobIndex]) {
NSMutableArray *mutableArray = [NSMutableArray new];
[mutableArray addObject:jobDB];
[self.jobsDataSource setValue:mutableArray forKey:jobIndex];
} else {
NSMutableArray *mutableArray = [self.jobsDataSource objectForKey:jobIndex];
if (![mutableArray containsObject:jobDB]) {
[mutableArray addObject:jobDB];
[self.jobsDataSource setValue:mutableArray forKey:jobIndex];
}
}
[self.jobsArray addObject:jobDB];
}
sortedKeys = [[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)];
}
- (void)refreshData {
[[ServiceManager sharedInstance] loadJobsWithCompletion:^(NSArray *responce, NSString *errorMessage) {
if ([self.refreshControl isRefreshing]) {
[self.refreshControl endRefreshing];
}
if (errorMessage) {
[[LogicManager sharedInstance] showAlertWithTitleKey:#"api_msg_error" AndMessage:errorMessage];
} else {
[self loadJobs];
}
}];
}
#pragma mark - Actions
- (IBAction)okButtonPressed:(id)sender {
if(self.selectedJobs.count == 0){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"jobs_select_title", nil) message:NSLocalizedString(#"jobs_no_job_msg", nil) delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
else{
if (self.jobsMode != Jobs_Mode_Lb && self.jobsMode != Jobs_Mode_Ad) {
BOOL hasSelectedHyperJob = FALSE;
NSMutableArray *tempArray = [NSMutableArray new];
NSMutableArray *tempHyperArray = [NSMutableArray new];
//Get selected hyperjobs for request
for(NSString *jobID in self.selectedJobs){
DBJobs *jobDB = [DBJobs MR_findFirstByAttribute:#"jobID" withValue:jobID];
if([jobDB.isM boolValue]){
hasSelectedHyperJob = TRUE;
[tempArray addObject:jobID];
}
}
//Check for verified hyperjobs in selected hyperjobs and remove them from request
for(NSString *jobID in tempArray){
for(NSString* selectedJobID in self.verifiedHyperjobs){
if([selectedJobID isEqualToString:jobID]){
[tempArray removeObject:jobID];
}
}
}
//Check for removed hyperjobs
for(NSString *jobID in self.verifiedHyperjobs){
BOOL isSelected = FALSE;
for(NSString* selectedJobID in self.selectedJobs){
if([selectedJobID isEqualToString:jobID]){
isSelected = TRUE;
}
}
if(isSelected == FALSE){
[tempHyperArray addObject:jobID];
}
}
//Remove deleted hyperjob
for (NSString *jobID in tempHyperArray){
[self.verifiedHyperjobs removeObject:jobID];
}
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.color = [UIColor whiteColor];
hud.labelColor = [UIColor blackColor];
hud.detailsLabelColor = [UIColor blackColor];
hud.mode = MBProgressHUDModeCustomView;
hud.customView = [LogicManager sharedInstance].HudActivity;
hud.dimBackground = YES;
//Request hyperjob
BOOL shouldReturn = FALSE;
for (NSString *jobID in tempArray){
[self.selectedJobs removeObject:jobID];
if([self.selectedJobs count] == 0){
//adding "Awaiting Status Verification" job
[self.selectedJobs addObject:#"57"];
}
shouldReturn = TRUE;
NSString *lang = #"en";
if([[LogicManager sharedInstance].deviceLanguage containsString:#"fr"]){
lang = #"fr";
}
[[ServiceManager sharedInstance] requestHyperjob:jobID forEmail:self.userEmail userID:self.userID language:lang lastName:self.userLastName andFirstName:self.userFirstName completion:^(id responce, NSString *errorMessage) {
if (!errorMessage && [responce[#"error"] intValue] == 0) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"hint_hyperjobs", nil) message:NSLocalizedString(#"hint_hyperjobs_txt", nil) delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
//show success
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"hint_hyperjobs", nil) message:NSLocalizedString(#"api_msg_error", nil) delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
}];
}
if(shouldReturn == TRUE){
return;
}
}
NSLog(#" selected jobs : %#", self.selectedJobs);
if (self.jobsMode == Jobs_Mode_Lb) {
[DataProvider sharedInstance].lbJobsArray = self.selectedJobs;
} else if (self.jobsMode == Jobs_Mode_Ad) {
[DataProvider sharedInstance].adJobsArray = self.selectedJobs;
} else {
[DataProvider sharedInstance].userJobsArray = self.selectedJobs;
}
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark - UITableView Delegate & DataSource1
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
JobsTableViewCell*cell = (JobsTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
// NSString *sectionTitle = [[[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.section];
// NSMutableArray *array = [self.jobsDataSource objectForKey:sectionTitle];
DBJobs *jobDB = [self.jobsArray objectAtIndex:indexPath.row];
[cell.jobNameLabel setFont:[UIFont fontWithName:#"DIN Alternate Bold" size:16]];
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(142.0/255.0) green:(142.0/255.0) blue:(142.0/255.0) alpha:1.0]];
if ([self.selectedJobs containsObject:jobDB.jobID]) {
if([jobDB.isM boolValue]){
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(210.0/255.0) green:(196.0/255.0) blue:(169.0/255.0) alpha:1.0]];
}
[self.selectedJobs removeObject:jobDB.jobID];
} else {
[self.selectedJobs addObject:jobDB.jobID];
[cell.jobNameLabel setFont:[UIFont fontWithName:#"DIN Alternate" size:20]];
if([jobDB.isM boolValue]){
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(168.0/255.0) green:(148.0/255.0) blue:(109.0/255.0) alpha:1.0]];
}
else{
[cell.jobNameLabel setTextColor:[UIColor blackColor]];
}
}
NSLog(#"selected jobs : %#", self.selectedJobs);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// return [[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)].count;
return 1;
}
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 40;
}
//- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
// return [[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)];
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// NSString *sectionTitle = [[[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)] objectAtIndex:section];
// NSArray *array = [self.jobsDataSource objectForKey:sectionTitle];
return [self.jobsArray count];
}
//- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
// NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:0 inSection:index];
// [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
// return index;
//}
//
//- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// return [[[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)] objectAtIndex:section];
//}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
JobsTableViewCell*cell = (JobsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"JobsTableViewCell"];
//NSString *sectionTitle = [sortedKeys objectAtIndex:indexPath.section];
// NSString *sectionTitle = [[[self.jobsDataSource allKeys] sortedArrayUsingSelector: #selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.section];
// NSMutableArray *array = [self.jobsDataSource objectForKey:sectionTitle];
DBJobs *jobDB = [self.jobsArray objectAtIndex:indexPath.row];
cell.width = self.view.width;
cell.jobNameLabel.text = [[LogicManager sharedInstance].deviceLanguage containsString:#"fr"] ? jobDB.name_fr : jobDB.name;
[cell.jobNameLabel setFont:[UIFont fontWithName:#"DIN Alternate Bold" size:16]];
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(142.0/255.0) green:(142.0/255.0) blue:(142.0/255.0) alpha:1.0]];
[cell setUserInteractionEnabled:TRUE];
if ([self.selectedJobs containsObject:jobDB.jobID]) {
[cell.jobNameLabel setFont:[UIFont fontWithName:#"DIN Alternate" size:20]];
if([jobDB.isM boolValue]){
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(168.0/255.0) green:(148.0/255.0) blue:(109.0/255.0) alpha:1.0]];
if(self.jobsMode != Jobs_Mode_Ad && self.jobsMode != Jobs_Mode_Lb){
[cell setUserInteractionEnabled:FALSE];
}
}
else{
[cell.jobNameLabel setTextColor:[UIColor blackColor]];
}
// [cell.contentView setBackgroundColor:[UIColor clearColor]];
} else {
// [cell.contentView setBackgroundColor:[UIColor grayColor]];
if([jobDB.isM boolValue]){
[cell.jobNameLabel setTextColor:[UIColor colorWithRed:(210.0/255.0) green:(196.0/255.0) blue:(169.0/255.0) alpha:1.0]];
}
}
return cell;
}
#pragma mark - UIAlertView Delegate Methods
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex{
[self okButtonPressed:0];
}
#end
// ServiceManager.m
#import "ServiceManager.h"
#import "LogicManager.h"
#import <MagicalRecord/MagicalRecord.h>
#import "DataProvider.h"
#import "DBJobs.h"
#import "Constants.h"
static NSString * const ApiJobsURLString = #"/api/v1/jobs/";
#pragma mark - JOBS
- (void)loadJobsWithCompletion:(void (^)(NSArray *responce,NSString * error))completion {
if (!self.isConnected) {
completion(nil, NSLocalizedString(#"msg_internet",nil));
return;
}
[self GET:ApiJobsURLString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
if (completion) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSArray *arrayResponce = [responseObject objectForKey:#"jobs"];
for (NSDictionary *dict in arrayResponce) {
[self saveJob:dict];
}
}
completion(responseObject, nil);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
if (!errorData) {
(error.code == -1005 || error.code == -1009) ? completion(nil, NSLocalizedString(#"msg_internet",nil)) : completion(nil, NSLocalizedString(error.description,nil));
return;
}
NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil];
NSString *errorMessage = [serializedData objectForKey:#"message"];
if (completion) {
completion(nil, NSLocalizedString(errorMessage,nil));
}
}];
}
Related
In my JSQMessagesViewController, when I load text message bubbles, the arrow direction is always right side.
How to change arrow direction to left for green bubbles??
My Code:
#interface AckChatViewController (){
JSQMessagesBubbleImage *outgoingBubbleImageView;
JSQMessagesBubbleImage *incomingBubbleImageView;
JSQMessagesAvatarImage *currentUserAvatar, *friendAvatar;
NSMutableArray *messages;
}
#end
#implementation AckChatViewController
pragma mark - life cycle methods
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.topItem.title = #"";
//initial things for JSQMessageViewController
[self setupBubbles];
messages = [NSMutableArray new];
AllUserDetailsModel *temp = [[AllUserDetailsModel alloc] initWithDictionary:[Neo_Constants getSavedDataFromUserDafaults:USER_INFO_DICTIONARY]];
self.senderId = [NSString stringWithFormat:#"%#",temp.user_id];
self.senderDisplayName = #"";
self.automaticallyScrollsToMostRecentMessage = YES;
//remove attachment button
self.inputToolbar.contentView.leftBarButtonItem = nil;
currentUserAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:temp.userDetails.gender]]]];
friendAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:self.friendUserDetails.userDetails.gender]]]];
NSString *imageUrlString = temp.userDetails.profile_pic;
[self avatarImagesForUrlString:imageUrlString andOnCompletion:^(UIImage *image) {
if(image){
currentUserAvatar.avatarImage = image;
}
}];
[self avatarImagesForUrlString:self.friendUserDetails.userDetails.profile_pic andOnCompletion:^(UIImage *image) {
if(image){
friendAvatar.avatarImage = image;
}
}];
//set profile pic and name on navigation bar
[self setNavigationBarTitleView];
[self loadPreviousChatWithPageCount:0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
pragma mark - JSQ Setups
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
pragma mark Collection view JSQ
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return messages.count;
}
-(id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
return messages[indexPath.item];
}
-(id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return outgoingBubbleImageView;
}else{
return incomingBubbleImageView;
}
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
[cell.textView setTextColor:[UIColor whiteColor]];
}else{
[cell.textView setTextColor:[UIColor blackColor]];
}
return cell;
}
-(id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return currentUserAvatar;
}else{
return friendAvatar;
}
}
-(void)collectionView:(JSQMessagesCollectionView *)collectionView header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessagesButton:(UIButton *)sender{
}
//time stamp
-(NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return nil;
}
-(CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return 0;
}
#pragma mark - private functions
-(NSString *)defaultImageForGender:(NSString *)gender{
if([gender isEqualToString:#"M"] || [gender isEqualToString:#""]){
return #"no_image_male";
}else{
return #"no_image_female";
}
}
-(void)setNavigationBarTitleView{
UIView *whole = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width - 100, 100)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 20, 50, 50)];
[imageView.layer setCornerRadius:25.0f];
[imageView setClipsToBounds:YES];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
if([self.friendUserDetails.userDetails.profile_pic isEqualToString:#""] || [self.friendUserDetails.userDetails.profile_pic isEqual:[NSNull null]]){
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
[imageView setImage:[UIImage imageNamed:#"no_image_male"]];
}else{
[imageView setImage:[UIImage imageNamed:#"no_image_female"]];
}
}else{
[imageView sd_setImageWithURL:[NSURL URLWithString:self.friendUserDetails.userDetails.profile_pic]];
}
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 20, [UIScreen mainScreen].bounds.size.width, 50)];
[nameLabel setText:self.friendUserDetails.userDetails.fname];
[whole addSubview:nameLabel];
[whole addSubview:imageView];
self.navigationItem.titleView = whole;
}
#pragma mark - Avtar images area
-(void)avatarImagesForUrlString:(NSString *)urlString andOnCompletion:(void(^)(UIImage *image))completion{
if([urlString isEqualToString:#""] || [urlString isEqual:[NSNull null]]){
completion(nil);
}else{
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:urlString] options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
completion ([self cropAvatarImages:image]);
}];
}
}
-(UIImage *)cropAvatarImages:(UIImage *)image{
if(image){
return [JSQMessagesAvatarImageFactory circularAvatarImage:image withDiameter:48];
}else{
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
return [UIImage imageNamed:#"no_image_male"];
}else{
return [UIImage imageNamed:#"no_image_female"];
}
}
}
#pragma mark - API calls
-(void)loadPreviousChatWithPageCount:(int)count{
[API fetchChatListOfUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
NSArray *conversation_data = [result objectForKey:#"conversation_data"];
[messages removeAllObjects];
[conversation_data enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop){
JSQMessage *jsqMsg = [[JSQMessage alloc] initWithSenderId:obj[#"sender_id"] senderDisplayName:#"" date:obj[#"sent_date"] text:obj[#"message_content"]];
[messages insertObject:jsqMsg atIndex:idx];
}];
[self.collectionView reloadData];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
-(void)didPressSendButton:(UIButton *)button withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date{
// [JSQSystemSoundPlayer jsq_playMessageSentSound];
[API sendMessageFromUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
[self loadPreviousChatWithPageCount:0];
[self.inputToolbar.contentView.textView setText:#""];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
#end
problem is in this code you initialise outgoing and incomming with the same method which is
outgoingMessagesBubbleImageWithColor
try incoming with
incomingMessagesBubbleImageWithColor
and outgoing with this
outgoingMessagesBubbleImageWithColor
this correct one
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
Thanks to #jsetting32 I have a custom UITableViewCell complete with buttons at the bottom of the tableView. However, when I am clicking those buttons, the value for the selectedState is not changing, making it a bit difficult for the end-user to tell if they have clicked it or not.
self.likeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.likeButton addTarget:self action:#selector(didTapLikeButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.likeButton setTitle:#"Pray" forState:UIControlStateNormal];
[self.likeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.likeButton setTitleColor:[UIColor blueColor] forState:UIControlStateSelected];
[[self.likeButton titleLabel] setFont:[UIFont fontWithName:#"Verdana" size:12.0f]];
[self.cellView addSubview:self.likeButton];
Try UIControlStateHighlighted instead of UIControlStateSelected
[self.likeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.likeButton setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
So heres how I solve the button issue... There should already be a method within your custom cell that sets the like status... It is set like so
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
if (indexPath.row == [self.objects count])
return [self tableView:tableView cellForNextPageAtIndexPath:indexPath];
PHChatCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[PHChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[cell setDelegate:self];
}
[self setCellAttributesWithCell:cell withObject:[self.object objectAtIndex:indexPath.row] withIndexPath:indexPath];
return cell;
}
- (void)setCellAttributesWithCell:(PHChatCell *)cell withObject:(PFObject *)object withIndexPath:(NSIndexPath *)indexPath
{
if (object) {
[cell setChat:object];
[cell setTag:indexPath.row];
[cell.likeButton setTag:indexPath.row];
if ([[PHCache sharedCache] attributesForMessage:object]) {
[cell setLikeStatus:[[PHCache sharedCache] isMessageLikedByCurrentUser:object]];
NSString *likeCount = [[[PHCache sharedCache] likeCountForMessage:object] description];
cell.likeCount.text = ([likeCount isEqualToString:#"1"]) ?
[NSString stringWithFormat:#"%# like", likeCount] :
[NSString stringWithFormat:#"%# likes", likeCount];
NSString *commentCount = [[[PHCache sharedCache] commentCountForMessage:object] description];
cell.commentCount.text = ([commentCount isEqualToString:#"1"]) ?
[NSString stringWithFormat:#"%# comment", commentCount] :
[NSString stringWithFormat:#"%# comments", commentCount];
return;
}
#synchronized(self) {
// Put this in your init method
// self.outstandingSectionHeadersQueries = [NSMutableDictionary dictionary]
if (![self.outstandingSectionHeaderQueries objectForKey:#(indexPath.row)]) {
PFQuery *query = [PHUtility queryForActivitiesOnMessage:object cachePolicy:kPFCachePolicyNetworkOnly];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
#synchronized(self) {
[self.outstandingSectionHeaderQueries removeObjectForKey:#(indexPath.row)];
if (error) return;
NSMutableArray *likers = [NSMutableArray array];
NSMutableArray *commenters = [NSMutableArray array];
BOOL isLikedByCurrentUser = NO;
for (PFObject *activity in objects) {
if ([[activity objectForKey:kPHActivityTypeKey] isEqualToString:kPHActivityTypeLike] && [activity objectForKey:kPHActivityFromUserKey]) {
[likers addObject:[activity objectForKey:kPHActivityFromUserKey]];
} else if ([[activity objectForKey:kPHActivityTypeKey] isEqualToString:kPHActivityTypeComment] && [activity objectForKey:kPHActivityFromUserKey]) {
[commenters addObject:[activity objectForKey:kPHActivityFromUserKey]];
}
if ([[[activity objectForKey:kPHActivityFromUserKey] objectId] isEqualToString:[[PFUser currentUser] objectId]] &&
[[activity objectForKey:kPHActivityTypeKey] isEqualToString:kPHActivityTypeLike]) {
isLikedByCurrentUser = YES;
}
}
[[PHCache sharedCache] setAttributesForMessage:object likers:likers commenters:commenters likedByCurrentUser:isLikedByCurrentUser];
if (cell.tag != indexPath.row) return;
[cell setLikeStatus:[[PHCache sharedCache] isMessageLikedByCurrentUser:object]];
NSString *likeCount = [[[PHCache sharedCache] likeCountForMessage:object] description];
cell.likeCount.text = ([likeCount isEqualToString:#"1"]) ?
[NSString stringWithFormat:#"%# like", likeCount] : [NSString stringWithFormat:#"%# likes", likeCount];
NSString *commentCount = [[[PHCache sharedCache] commentCountForMessage:object] description];
cell.commentCount.text = ([commentCount isEqualToString:#"1"]) ?
[NSString stringWithFormat:#"%# comment", commentCount] : [NSString stringWithFormat:#"%# comments", commentCount];
}
}];
}
}
}
}
- (void)PHChatCell:(PHChatCell *)cell didTapLikeButton:(UIButton *)button chat:(PFObject *)chat
{
// Disable the button so users cannot send duplicate requests
[cell shouldEnableLikeButton:NO];
//These are private interface properties to handle when the user wants to unlike the prayer
//when the UIActionsheet is loaded
self.chat = chat;
self.likeButton = button;
self.cell = cell;
if (button.selected) {
[[[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Unlike" otherButtonTitles:nil] showInView:self.view];
return;
}
BOOL liked = !button.selected;
[cell setLikeStatus:liked];
NSString *originalButtonTitle = button.titleLabel.text;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
NSNumber *likeCount = [numberFormatter numberFromString:button.titleLabel.text];
[button setTitle:#"Liked" forState:UIControlStateNormal];
[UIView animateWithDuration:0.25 animations:^{
[cell.likeImage setImage:[UIImage imageNamed:#"ButtonLikeSelected.png"]];
[cell.likeImage setTransform:CGAffineTransformMakeScale(1.5, 1.5)];
} completion:^(BOOL finished){
[UIView animateWithDuration:0.25 animations:^{
[cell.likeImage setTransform:CGAffineTransformMakeScale(1, 1)];
}];
}];
NSInteger checker = [[cell.likeCount text] integerValue] + 1;
cell.likeCount.text = (checker == 1) ?
[NSString stringWithFormat:#"%ld like", (long)checker] :
[NSString stringWithFormat:#"%ld likes", (long)checker];
likeCount = [NSNumber numberWithInt:[likeCount intValue] + 1];
[[PHCache sharedCache] incrementLikerCountForMessage:chat];
[[PHCache sharedCache] setMessageIsLikedByCurrentUser:chat liked:liked];
[PHUtility likeMessageInBackground:chat block:^(BOOL succeeded, NSError *error) {
PHChatCell *actualCell = (PHChatCell *)[self tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:button.tag inSection:0]];
[actualCell shouldEnableLikeButton:YES];
[actualCell setLikeStatus:succeeded];
if (!succeeded) {
[actualCell.likeButton setTitle:originalButtonTitle forState:UIControlStateNormal];
}
}];
}
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
BOOL liked = !self.likeButton.selected;
[self.cell setLikeStatus:liked];
[self.likeButton setTitle:#"Like" forState:UIControlStateNormal];
[self.cell.likeImage setImage:[UIImage imageNamed:#"ButtonLike.png"]];
NSInteger checker = [[self.cell.likeCount text] integerValue] - 1;
self.cell.likeCount.text = (checker == 1) ?
[NSString stringWithFormat:#"%ld like", (long)checker] :
[NSString stringWithFormat:#"%ld likes", (long)checker];
NSString *originalButtonTitle = self.likeButton.titleLabel.text;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
NSNumber *likeCount = [numberFormatter numberFromString:self.likeButton.titleLabel.text];
likeCount = [NSNumber numberWithInt:[likeCount intValue] + 1];
if ([likeCount intValue] > 0) {
likeCount = [NSNumber numberWithInt:[likeCount intValue] - 1];
}
[[PHCache sharedCache] decrementLikerCountForMessage:self.chat];
[[PHCache sharedCache] setMessageIsLikedByCurrentUser:self.chat liked:NO];
[PHUtility unlikeMessageInBackground:self.chat block:^(BOOL succeeded, NSError *error) {
PHChatCell *actualCell = (PHChatCell *)[self tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:self.likeButton.tag inSection:0]];
[actualCell shouldEnableLikeButton:YES];
[actualCell setLikeStatus:!succeeded];
if (!succeeded) {
[actualCell.likeButton setTitle:originalButtonTitle forState:UIControlStateNormal];
}
}];
}
}
Here is the query method used in the previous snippet of code (declared in PHUtility class) :
+ (PFQuery *)queryForActivitiesOnMessage:(PFObject *)message cachePolicy:(PFCachePolicy)cachePolicy {
PFQuery *queryLikes = [PFQuery queryWithClassName:kPHActivityClassKey];
[queryLikes whereKey:kPHActivityMessageKey equalTo:message];
[queryLikes whereKey:kPHActivityTypeKey equalTo:kPHActivityTypeLike];
PFQuery *queryComments = [PFQuery queryWithClassName:kPHActivityClassKey];
[queryComments whereKey:kPHActivityMessageKey equalTo:message];
[queryComments whereKey:kPHActivityTypeKey equalTo:kPHActivityTypeComment];
PFQuery *query = [PFQuery orQueryWithSubqueries:[NSArray arrayWithObjects:queryLikes,queryComments,nil]];
[query setCachePolicy:cachePolicy];
[query includeKey:kPHActivityFromUserKey];
[query includeKey:kPHActivityMessageKey];
return query;
}
Here are the PHCache implementation ...
#interface PHCache()
#property (nonatomic, strong) NSCache *cache;
- (void)setAttributes:(NSDictionary *)attributes forMessage:(PFObject *)message;
#end
#implementation PHCache
#synthesize cache;
#pragma mark - Initialization
+ (id)sharedCache {
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
- (id)init {
self = [super init];
if (self) {
self.cache = [[NSCache alloc] init];
}
return self;
}
- (void)clear {
[self.cache removeAllObjects];
}
- (void)setAttributes:(NSDictionary *)attributes forMessage:(PFObject *)message {
[self.cache setObject:attributes forKey:[self keyForMessage:message]];
}
- (NSString *)keyForMessage:(PFObject *)message {
return [NSString stringWithFormat:#"message_%#", [message objectId]];
}
#pragma mark - Global Chat
- (void)setAttributesForMessage:(PFObject *)message
likers:(NSArray *)likers
commenters:(NSArray *)commenters
likedByCurrentUser:(BOOL)likedByCurrentUser {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:likedByCurrentUser],kPHMessageAttributesIsLikedByCurrentUserKey,
#([likers count]),kPHMessageAttributesLikeCountKey,
likers,kPHMessageAttributesLikersKey,
#([commenters count]),kPHMessageAttributesCommentCountKey,
commenters,kPHMessageAttributesCommentersKey,
nil];
[self setAttributes:attributes forMessage:message];
}
- (NSDictionary *)attributesForMessage:(PFObject *)message {
return [self.cache objectForKey:[self keyForMessage:message]];
}
- (NSNumber *)likeCountForMessage:(PFObject *)message {
NSDictionary *attributes = [self attributesForMessage:message];
if (attributes) {
return [attributes objectForKey:kPHMessageAttributesLikeCountKey];
}
return [NSNumber numberWithInt:0];
}
- (NSNumber *)commentCountForMessage:(PFObject *)message {
NSDictionary *attributes = [self attributesForMessage:message];
if (attributes) {
return [attributes objectForKey:kPHMessageAttributesCommentCountKey];
}
return [NSNumber numberWithInt:0];
}
- (NSArray *)likersForMessage:(PFObject *)message {
NSDictionary *attributes = [self attributesForMessage:message];
if (attributes) {
return [attributes objectForKey:kPHMessageAttributesLikersKey];
}
return [NSArray array];
}
- (NSArray *)commentersForMessage:(PFObject *)message {
NSDictionary *attributes = [self attributesForMessage:message];
if (attributes) {
return [attributes objectForKey:kPHMessageAttributesCommentersKey];
}
return [NSArray array];
}
- (void)setMessageIsLikedByCurrentUser:(PFObject *)message liked:(BOOL)liked {
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForMessage:message]];
[attributes setObject:[NSNumber numberWithBool:liked] forKey:kPHMessageAttributesIsLikedByCurrentUserKey];
[self setAttributes:attributes forMessage:message];
}
- (BOOL)isMessageLikedByCurrentUser:(PFObject *)message {
NSDictionary *attributes = [self attributesForMessage:message];
if (attributes) {
return [[attributes objectForKey:kPHMessageAttributesIsLikedByCurrentUserKey] boolValue];
}
return NO;
}
- (void)incrementLikerCountForMessage:(PFObject *)message {
NSNumber *likerCount = [NSNumber numberWithInt:[[self likeCountForMessage:message] intValue] + 1];
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForMessage:message]];
[attributes setObject:likerCount forKey:kPHMessageAttributesLikeCountKey];
[self setAttributes:attributes forMessage:message];
}
- (void)decrementLikerCountForMessage:(PFObject *)message {
NSNumber *likerCount = [NSNumber numberWithInt:[[self likeCountForMessage:message] intValue] - 1];
if ([likerCount intValue] < 0) {
return;
}
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForMessage:message]];
[attributes setObject:likerCount forKey:kPHMessageAttributesLikeCountKey];
[self setAttributes:attributes forMessage:message];
}
- (void)incrementCommentCountForMessage:(PFObject *)message {
NSNumber *commentCount = [NSNumber numberWithInt:[[self commentCountForMessage:message] intValue] + 1];
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForMessage:message]];
[attributes setObject:commentCount forKey:kPHMessageAttributesCommentCountKey];
[self setAttributes:attributes forMessage:message];
}
- (void)decrementCommentCountForMessage:(PFObject *)message {
NSNumber *commentCount = [NSNumber numberWithInt:[[self commentCountForMessage:message] intValue] - 1];
if ([commentCount intValue] < 0) {
return;
}
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForMessage:message]];
[attributes setObject:commentCount forKey:kPHMessageAttributesCommentCountKey];
[self setAttributes:attributes forMessage:message];
}
- (NSNumber *)messageCountForUser:(PFUser *)user {
NSDictionary *attributes = [self attributesForUser:user];
if (attributes) {
NSNumber *photoCount = [attributes objectForKey:kPHUserAttributesMessageCountKey];
if (photoCount) {
return photoCount;
}
}
return [NSNumber numberWithInt:0];
}
- (void)setMessageCount:(NSNumber *)count user:(PFUser *)user {
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self attributesForUser:user]];
[attributes setObject:count forKey:kPHUserAttributesMessageCountKey];
[self setAttributes:attributes forUser:user];
}
Like I said in your previous post... It requires a hefty amount of code to make this feature 'optimal'... Reason for the cache object is to limit api requests to the servers. If the cell has been loaded, we're gonna check the cache to see if the attributes for the cell have been loaded, if it hasn't query to the server to get the attributes and set the cache to ensure we don't need to make an api request in the future...
All the variables starting with kPH are constants that you can declare on your own, or how you feel is sufficient... Like I said before, checking out the Anypic project and integrating the features into your app is best. Just copy over the PAPCache class and PAPUtility class over. Just make sure you read over the code to fully understand what is going on to get a better sense of how to integrate the code with yours, and to extend it to add more features to your app.
If you have any issues please feel free to post a comment.
i. While touching use UIControlStateHighlighted as suggested above.
ii. Keep a different color:
Since you have a custom UITableViewCell, you should implement an IBAction and set your UIButton to this using
[self.likeButton addTarget:self action:#selector(select:) forControlEvents:UIControlEventTouchUpInside];
in the .m file of your cell set:
-(IBAction)onSelectCellClicked:(id)sender {
if(self.yourButton.selected) {
self.yourButton.selected = NO;
} else {
self.yourButton.selected = YES;
}
}
Now set the cell's delegate to self in cell for row after putting this in the cell's .h file:
#protocol CustomCellDelegate <NSObject>
#end
#interface CustomCell : UITableViewCell
#property (strong, nonatomic) NSObject<CustomCellDelegate>* delegate;
#end
And put in the VC that is presenting the UITableView using the custom cell.
you can just add this line into 'didTapLikeButtonAction' :
self.likeButton.selected = !self.likeButton.selected;
once you change the selected state, the button will change its title color.
you may also want to add this line for a smoother effect:
[self.likeButton setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
I'm developing a view controller for a chat application and I want to show a UIViewController that contains a UITableView (where messages are shown with different format [if is your message or if is a message from other person], a UITextField (to write your messages) and a UIButton (to send the message)
I'm using SRWebSocket example but they use a UITableViewController (that runs perfectly but don't allow me to modify tableview size or to add the others components to the view by storyboard)
This is the code that I have in my Controller:
ChatViewController.h
#import <UIKit/UIKit.h>
#import "SRWebSocket.h"
#import "ChatCell.h"
#import "Message.h"
#import "Person.h"
#import "Program.h"
#import "DateFactory.h"
#interface ChatViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,SRWebSocketDelegate, UITextViewDelegate, UITextFieldDelegate>
#property (strong, nonatomic) NSDictionary *programSegue;
#property (retain, nonatomic) IBOutlet UITableView *tableView;
#property (nonatomic, retain) IBOutlet UITextView *inputView;
- (IBAction)goingUp:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *inputText;
#end
ChatViewController.m
Code that fails:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
in:
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
{
NSLog(#"Received \"%#\"", message);
NSError *e;
NSDictionary *allJSON =
[NSJSONSerialization JSONObjectWithData: [message dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &e];
NSString *kindJSON = [allJSON objectForKey:#"kind"];
NSString *userJSON = [allJSON objectForKey:#"user"];
NSString *messageJSON = [allJSON objectForKey:#"message"];
NSArray *membersJSON = [allJSON objectForKey:#"members"];
DateFactory *dateFactory = [DateFactory alloc];
NSString *formatDate = #"dd/MM/YYYY HH:mm";
NSString *dateString = [dateFactory dateToString:[NSDate date] withFormat:formatDate];
switch([#[#"join", #"talk", #"quit"] indexOfObject:kindJSON]){
// join
case 0:
break;
// talk
case 1:
[_messages addObject:[[Message alloc] initWithMessage:messageJSON fromMe:NO]];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
break;
// quit
case 2:
[[self.navigationItem.titleView.subviews objectAtIndex:1] setText:
[NSString stringWithFormat:#"Sin conexión desde %#", dateString]];
break;
}
}
ERROR
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'
Full code:
#import "ChatViewController.h"
#interface ChatViewController ()
#end
#implementation ChatViewController{
SRWebSocket *_webSocket;
NSMutableArray *_messages;
Person *person;
Program *program;
}
#synthesize programSegue;
#synthesize tableView;
#synthesize inputText;
#synthesize inputView = _inputView;
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
return [inputText resignFirstResponder];
}
#pragma mark - View lifecycle
- (void)viewDidLoad;
{
[super viewDidLoad];
[inputText setDelegate:self];
person = [programSegue objectForKey:#"PERSON"];
program = [programSegue objectForKey:#"PROGRAM"];
self.navigationItem.title = person.name;
// Creates picture to be shown in navigation bar
UIButton* picture = (UIButton *) [[UIImageView alloc] initWithImage:[UIImage imageNamed:person.imageURL]];
CGRect buttonFrame = picture.frame;
buttonFrame.size = CGSizeMake(38, 38);
picture.frame = buttonFrame;
UIBarButtonItem *pictureItem = [[UIBarButtonItem alloc] initWithCustomView:picture];
self.navigationItem.rightBarButtonItem = pictureItem;
// Set title and subtitle
CGRect frame = self.navigationController.navigationBar.frame;
UIView *twoLineTitleView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(frame), 0, CGRectGetWidth(frame), CGRectGetHeight(frame))];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 6, CGRectGetWidth(frame), 20)];
titleLabel.backgroundColor = [UIColor clearColor];
[titleLabel setTextColor:[UIColor whiteColor]];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[titleLabel setTextAlignment:NSTextAlignmentCenter];
[titleLabel setFont:[UIFont boldSystemFontOfSize:16]];
[titleLabel setShadowColor:[UIColor grayColor]];
titleLabel.text = person.name;
[twoLineTitleView addSubview:titleLabel];
UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 26, CGRectGetWidth(frame), 14)];
subTitleLabel.backgroundColor = [UIColor clearColor];
[subTitleLabel setTextColor:[UIColor whiteColor]];
subTitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[subTitleLabel setTextAlignment:NSTextAlignmentCenter];
[subTitleLabel setFont:[UIFont boldSystemFontOfSize:12]];
[titleLabel setShadowColor:[UIColor grayColor]];
subTitleLabel.text = #"subtitleg";
[twoLineTitleView addSubview:subTitleLabel];
self.navigationItem.titleView = twoLineTitleView;
// Start messages
_messages = [[NSMutableArray alloc] init];
[self.tableView reloadData];
}
- (void)_reconnect;
{
_webSocket.delegate = nil;
[_webSocket close];
_webSocket = [[SRWebSocket alloc] initWithURLRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:
[NSString stringWithFormat:#"ws://81.45.19.228:8000/room/chat?username=enrimr&pid=%#", person.name]]]];
_webSocket.delegate = self;
//self.title = #"Opening Connection...";
[[self.navigationItem.titleView.subviews objectAtIndex:1] setText:#"Conectando..."];
[_webSocket open];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self _reconnect];
}
- (void)reconnect:(id)sender;
{
[self _reconnect];
}
- (void)viewDidAppear:(BOOL)animated;
{
[super viewDidAppear:animated];
[_inputView becomeFirstResponder];
[self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
_webSocket.delegate = nil;
[_webSocket close];
_webSocket = nil;
}
#pragma mark - UITableViewController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return _messages.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
{
ChatCell *chatCell = (id)cell;
Message *message = [_messages objectAtIndex:indexPath.row];
chatCell.text.text = message.message;
chatCell.date.text = message.fromMe ? #"Me" : #"Other";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
Message *message = [_messages objectAtIndex:indexPath.row];
ChatCell *cell = (ChatCell *)[self.tableView dequeueReusableCellWithIdentifier:#"programCell" forIndexPath:indexPath];
if (!cell) {
if (message.fromMe){
cell = [[ChatCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SentCell"];
[cell.text setText:message.message];
[cell.date setText:#"00:00"];
}
else {
cell = [[ChatCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"ReceivedCell"];
[cell.text setText:message.message];
[cell.date setText:#"00:00"];
}
}
return cell;
}
#pragma mark - SRWebSocketDelegate
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
{
NSLog(#"Websocket Connected");
//self.title = #"Connected!";
[[self.navigationItem.titleView.subviews objectAtIndex:1] setText:#"Conectado"];
}
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
{
NSLog(#":( Websocket Failed With Error %#", error);
self.title = #"Connection Failed! (see logs)";
_webSocket = nil;
}
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
{
NSLog(#"Received \"%#\"", message);
NSError *e;
NSDictionary *allJSON =
[NSJSONSerialization JSONObjectWithData: [message dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &e];
NSString *kindJSON = [allJSON objectForKey:#"kind"];
NSString *userJSON = [allJSON objectForKey:#"user"];
NSString *messageJSON = [allJSON objectForKey:#"message"];
NSArray *membersJSON = [allJSON objectForKey:#"members"];
DateFactory *dateFactory = [DateFactory alloc];
NSString *formatDate = #"dd/MM/YYYY HH:mm";
NSString *dateString = [dateFactory dateToString:[NSDate date] withFormat:formatDate];
switch([#[#"join", #"talk", #"quit"] indexOfObject:kindJSON]){
// join
case 0:
break;
// talk
case 1:
[_messages addObject:[[Message alloc] initWithMessage:messageJSON fromMe:NO]];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
break;
// quit
case 2:
[[self.navigationItem.titleView.subviews objectAtIndex:1] setText:
[NSString stringWithFormat:#"Sin conexión desde %#", dateString]];
break;
}
}
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
{
NSLog(#"WebSocket closed");
//self.title = #"Connection Closed! (see logs)";
[[self.navigationItem.titleView.subviews objectAtIndex:1] setText:#"Offline"];
_webSocket = nil;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
{
if ([text rangeOfString:#"\n"].location != NSNotFound) {
NSString *message = [[textView.text stringByReplacingCharactersInRange:range withString:text] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[_webSocket send:message];
[_messages addObject:[[Message alloc] initWithMessage:message fromMe:YES]];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
textView.text = #"";
return NO;
}
return YES;
}
- (void) animateTextField: (UITextField*) textField up: (BOOL)up
{
const int movementDistance = 218;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
- (IBAction)goingUp:(id)sender {
[self animateTextField:inputText up:TRUE];
}
#end
When you use insertRowsAtIndexPaths you have to first update the table view data source. So before you call the insertRowsAtIndexPaths you should do something like _messages addObject:newMessage.
Just as a helper rule, whenever you update the rows of a table view without using reloadData method, you have to update the tableView`s data source to reflect the index paths that will be updated. So if you delete on row from your table view, the data associated with that row must be deleted from data source, also if you add a row to the table view, you have to add the associated data of the new row into the data source. ALWAYS UPDATE THE DATASOURCE FIRST.
And every time you update the rows of a table view you should use the update method between beginUpdates and endUpdates method calls.
The problem was that I forgot to set
[tableView setDataSource:self];
[tableView setDelegate:self];
in my viewDidLoad. These two lines will fix my problem.
i tried the following code for searching in epub ,Its not working the reason is
1.The table delegate methode executing at startup so the default value of search results is 0 ,so i give one dummy array with 4 elements in viewdidload method.So now tableview displaying only 4 thode elements in dummy array and when i scroll the tableview it displaying correct search results but still it showing only 4 elemets in that search results because number of rows methode is not execute while scrolling.
when i click search button it will call this methode in first class
SearchResultsViewController *searchRes=[[SearchResultsViewController alloc]initWithNibName:#"SearchResultsViewController" bundle:nil];
NSString *searchQuery=[search text];
sharedManager=[Mymanager sharedManager];
sharedManager.searchQuery=searchQuery;
// UITextField *textField = [NSString stringWithFormat:#"%#",searchQuery];
// [textField setFont:[UIFont fontWithName:#"BL-Ruthika-Bold" size:15]];
[searchRes searchString:searchQuery];
[self.navigationController pushViewController:searchRes animated:YES];
then it calls following methods in searchresult class
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"%d",[results count]);
if([results count]>0)
{
return [results count];
}
else
{
return [test count];
}
}
//executes only at the startup time ,so the value of results always become zero
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
if([results count]>0) {
// cell.textLabel.adjustsFontSizeToFitWidth = YES;
hit = (SearchResult*)[results objectAtIndex:[indexPath row]];
cell.textLabel.text = [NSString stringWithFormat:#"...%#...", hit.neighboringText];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Chapter %d - page %d", hit.chapterIndex, hit.pageIndex+1];
cell.textLabel.font = [UIFont fontWithName:#"Trebuchet MS" size:13];
cell.textLabel.textColor = [UIColor colorWithRed:25/255.0 green:90/255.0 blue:100/255.0 alpha:1];
cell.detailTextLabel.textColor=[UIColor colorWithRed:25/255.0 green:90/255.0 blue:100/255.0 alpha:1];
cell.detailTextLabel.font= [UIFont fontWithName:#"Trebuchet MS" size:10];
return cell;
}
else
{
cell.textLabel.text=[test objectAtIndex:indexPath.row];
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sharedManager=[Mymanager sharedManager];
hit = (SearchResult*)[results objectAtIndex:[indexPath row]];
sharedManager.searchFlag=YES;
sharedManager.hitPageNumber=hit.pageIndex;
sharedManager.hitChapter=hit.chapterIndex;
sharedManager.hit=hit;
// [fvc loadSpine:hit.chapterIndex atPageIndex:hit.pageIndex highlightSearchResult:hit];
[self.navigationController popViewControllerAnimated:YES];
}
- (void) searchString:(NSString*)query{
currentQuery=sharedManager.searchQuery;
[self searchString:currentQuery inChapterAtIndex:0];
[[self resultsTableView]reloadData];
}
- (void) searchString:(NSString *)query inChapterAtIndex:(int)index{
currentChapterIndex = index;
sharedManager=[Mymanager sharedManager];
Chapter* chapter = [sharedManager.spineArray objectAtIndex:index];
NSRange range = NSMakeRange(0, chapter.text.length);
NSLog(#"%#",sharedManager.searchQuery);
range = [chapter.text rangeOfString:sharedManager.searchQuery options:NSCaseInsensitiveSearch range:range locale:nil];
int hitCount=0;
while (range.location != NSNotFound) {
range = NSMakeRange(range.location+range.length, chapter.text.length-(range.location+range.length));
range = [chapter.text rangeOfString:sharedManager.searchQuery options:NSCaseInsensitiveSearch range:range locale:nil];
hitCount++;
}
if(hitCount!=0){
UIWebView* webView = [[UIWebView alloc] initWithFrame:chapter.windowSize];
[webView setDelegate:self];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:chapter.spinePath]];
[webView loadRequest:urlRequest];
} else {
if((currentChapterIndex+1)<[sharedManager.spineArray count]){
[self searchString:sharedManager.searchQuery inChapterAtIndex:(currentChapterIndex+1)];
} else {
fvc.searching = NO;
}
}
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
// NSLog(#"%#", error);
[webView release];
}
- (void) webViewDidFinishLoad:(UIWebView*)webView{
sharedManager=[Mymanager sharedManager];
NSString *varMySheet = #"var mySheet = document.styleSheets[0];";
NSString *addCSSRule = #"function addCSSRule(selector, newRule) {"
"if (mySheet.addRule) {"
"mySheet.addRule(selector, newRule);" // For Internet Explorer
"} else {"
"ruleIndex = mySheet.cssRules.length;"
"mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);" // For Firefox, Chrome, etc.
"}"
"}";
NSString *insertRule1 = [NSString stringWithFormat:#"addCSSRule('html', 'padding: 0px; height: %fpx; -webkit-column-gap: 0px; -webkit-column-width: %fpx;')", webView.frame.size.height, webView.frame.size.width];
NSString *insertRule2 = [NSString stringWithFormat:#"addCSSRule('p', 'text-align: justify;')"];
NSString *setTextSizeRule = [NSString stringWithFormat:#"addCSSRule('body', '-webkit-text-size-adjust: %d%%;')",[[sharedManager.spineArray objectAtIndex:currentChapterIndex] fontPercentSize]];
[webView stringByEvaluatingJavaScriptFromString:varMySheet];
[webView stringByEvaluatingJavaScriptFromString:addCSSRule];
[webView stringByEvaluatingJavaScriptFromString:insertRule1];
[webView stringByEvaluatingJavaScriptFromString:insertRule2];
[webView stringByEvaluatingJavaScriptFromString:setTextSizeRule];
[webView highlightAllOccurencesOfString:sharedManager.searchQuery];
NSString* foundHits = [webView stringByEvaluatingJavaScriptFromString:#"results"];
NSLog(#"%#", foundHits);
NSMutableArray* objects = [[NSMutableArray alloc] init];
NSArray* stringObjects = [foundHits componentsSeparatedByString:#";"];
for(int i=0; i<[stringObjects count]; i++){
NSArray* strObj = [[stringObjects objectAtIndex:i] componentsSeparatedByString:#","];
if([strObj count]==3){
[objects addObject:strObj];
}
}
NSArray* orderedRes = [objects sortedArrayUsingComparator:^(id obj1, id obj2){
int x1 = [[obj1 objectAtIndex:0] intValue];
int x2 = [[obj2 objectAtIndex:0] intValue];
int y1 = [[obj1 objectAtIndex:1] intValue];
int y2 = [[obj2 objectAtIndex:1] intValue];
if(y1<y2){
return NSOrderedAscending;
} else if(y1>y2){
return NSOrderedDescending;
} else {
if(x1<x2){
return NSOrderedAscending;
} else if (x1>x2){
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
}];
[objects release];
for(int i=0; i<[orderedRes count]; i++){
NSArray* currObj = [orderedRes objectAtIndex:i];
SearchResult* searchRes = [[SearchResult alloc] initWithChapterIndex:currentChapterIndex pageIndex:([[currObj objectAtIndex:1] intValue]/webView.bounds.size.height) hitIndex:0 neighboringText:[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"unescape('%#')", [currObj objectAtIndex:2]]] originatingQuery:sharedManager.searchQuery];
[results addObject:searchRes];
[searchRes release];
}
[[self resultsTableView]reloadData];
//Print results
for(int i=0;i<[results count];i++)
{
hit = (SearchResult*)[results objectAtIndex:i];
}
[resultsTableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
if((currentChapterIndex+1)<[sharedManager.spineArray count]){
[self searchString:sharedManager.searchQuery inChapterAtIndex:(currentChapterIndex+1)];
} else {
fvc.searching= NO;
}
[[self resultsTableView]reloadData];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
resultsTableView=[[UITableView alloc]init];
[resultsTableView setDelegate:self];
[resultsTableView setDataSource:self];
sharedManager=[Mymanager sharedManager];
// Do any additional setup after loading the view from its nib.
results = [[NSMutableArray alloc] init];
test=[[NSArray alloc]initWithObjects:#"one",#"one",#"one",#"one",nil];
self.navigationItem.title=#"Search ";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem=backButton;
[[UINavigationBar appearance] setTitleTextAttributes: #{
UITextAttributeTextColor: [UIColor whiteColor],
UITextAttributeTextShadowColor: [UIColor lightGrayColor],
UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0.0f, 1.0f)],
UITextAttributeFont: [UIFont fontWithName:#"Trebuchet MS" size:15.0f]
}];
[self searchString:sharedManager.searchQuery];
noMatchingSearch=[[NSArray alloc]initWithObjects:#"No Element Found", nil];
tableOfContents=[[NSMutableArray alloc]init];
for (id img in search.subviews)
{
if ([img isKindOfClass:NSClassFromString(#"UISearchBarBackground")])
{
[img removeFromSuperview];
}
}
tableOfContents=[sharedManager.List copy];
}
- (void)viewDidUnload
{
search = nil;
[super viewDidUnload];
resultsTableView.delegate=self;
resultsTableView.dataSource=self;
// Release any retained subviews of the main view.
self.resultsTableView = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
When you have received your search results call
[self.tableView reloadData];
To tell the table view to update itself. I can see you have tried it a number of times in the large amount of code above. You only need to call it once, when you have your search results ready. Also, ensure your reference to the table view is valid when you call it.
Also, if you're creating a table view in an XIB file, then the second one you're creating in viewDidLoad and not showing (adding as a subview) is just confusing you and you're trying to reload the wrong table view.
If you still have problems, show the class properties and remove all the code tat isn't to do with the table view.
resultsTableView=[[UITableView alloc]init];
Try to use resultsTableView, with a property, and set it's to (nonatomic, strong).
When i click search it executes a search class and after finding the results it executes numberOfRows method but then it is showing empty table. It is not executing cellForRowAtIndexPath method .
check my below code
code in viewcontroller.h
when i click search button this method will get executed
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
SearchResultsViewController *searchRes=[[SearchResultsViewController alloc]initWithNibName:#"SearchResultsViewController" bundle:nil];
NSString *searchQuery=[search text];
sharedManager=[Mymanager sharedManager];
sharedManager.searchQuery=searchQuery;
[searchRes searchString:searchQuery];
[self.navigationController pushViewController:searchRes animated:YES];
}
in search class
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"%#",results);
return [results count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.adjustsFontSizeToFitWidth = YES;
NSLog(#"indexpath%d",indexPath.row);
NSLog(#"%#",[results objectAtIndex:[indexPath row]]);
SearchResult* hit = (SearchResult*)[results objectAtIndex:[indexPath row]];
NSLog(#"%#",hit.neighboringText);
cell.textLabel.text = [NSString stringWithFormat:#"...%#...", hit.neighboringText];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Chapter %d - page %d", hit.chapterIndex, hit.pageIndex+1];
cell.textLabel.font = [UIFont fontWithName:#"Trebuchet MS" size:12];
cell.textLabel.textColor = [UIColor colorWithRed:25/255.0 green:90/255.0 blue:100/255.0 alpha:1];
// else
// {
//
// }
// [[self resultsTableView] reloadData];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SearchResult* hit = (SearchResult*)[results objectAtIndex:[indexPath row]];
[fvc loadSpine:hit.chapterIndex atPageIndex:hit.pageIndex highlightSearchResult:hit];
}
- (void) searchString:(NSString*)query{
// if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// {
self.results = [[NSMutableArray alloc] init];
[resultsTableView reloadData];
currentQuery=sharedManager.searchQuery;
//
[self searchString:currentQuery inChapterAtIndex:0];
//
// }else {
// currentQuery=sharedManager.searchQuery;
// [self searchString:currentQuery inChapterAtIndex:0];
//}
}
- (void) searchString:(NSString *)query inChapterAtIndex:(int)index{
currentChapterIndex = index;
sharedManager=[Mymanager sharedManager];
Chapter* chapter = [sharedManager.spineArray objectAtIndex:index];
NSLog(#"%d",chapter.text.length);
NSRange range = NSMakeRange(0, chapter.text.length);
NSLog(#"%#",sharedManager.searchQuery);
range = [chapter.text rangeOfString:sharedManager.searchQuery options:NSCaseInsensitiveSearch range:range locale:nil];
int hitCount=0;
while (range.location != NSNotFound) {
range = NSMakeRange(range.location+range.length, chapter.text.length-(range.location+range.length));
range = [chapter.text rangeOfString:sharedManager.searchQuery options:NSCaseInsensitiveSearch range:range locale:nil];
hitCount++;
}
if(hitCount!=0){
UIWebView* webView = [[UIWebView alloc] initWithFrame:chapter.windowSize];
[webView setDelegate:self];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:chapter.spinePath]];
[webView loadRequest:urlRequest];
} else {
if((currentChapterIndex+1)<[sharedManager.spineArray count]){
[self searchString:sharedManager.searchQuery inChapterAtIndex:(currentChapterIndex+1)];
} else {
fvc.searching = NO;
}
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(#"%#", error);
[webView release];
}
- (void) webViewDidFinishLoad:(UIWebView*)webView{
NSString *varMySheet = #"var mySheet = document.styleSheets[0];";
NSString *addCSSRule = #"function addCSSRule(selector, newRule) {"
"if (mySheet.addRule) {"
"mySheet.addRule(selector, newRule);" // For Internet Explorer
"} else {"
"ruleIndex = mySheet.cssRules.length;"
"mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);" // For Firefox, Chrome, etc.
"}"
"}";
NSString *insertRule1 = [NSString stringWithFormat:#"addCSSRule('html', 'padding: 0px; height: %fpx; -webkit-column-gap: 0px; -webkit-column-width: %fpx;')", webView.frame.size.height, webView.frame.size.width];
NSString *insertRule2 = [NSString stringWithFormat:#"addCSSRule('p', 'text-align: justify;')"];
NSString *setTextSizeRule = [NSString stringWithFormat:#"addCSSRule('body', '-webkit-text-size-adjust: %d%%;')",[[sharedManager.spineArray objectAtIndex:currentChapterIndex] fontPercentSize]];
[webView stringByEvaluatingJavaScriptFromString:varMySheet];
[webView stringByEvaluatingJavaScriptFromString:addCSSRule];
[webView stringByEvaluatingJavaScriptFromString:insertRule1];
[webView stringByEvaluatingJavaScriptFromString:insertRule2];
[webView stringByEvaluatingJavaScriptFromString:setTextSizeRule];
[webView highlightAllOccurencesOfString:sharedManager.searchQuery];
NSString* foundHits = [webView stringByEvaluatingJavaScriptFromString:#"results"];
NSLog(#"%#", foundHits);
NSMutableArray* objects = [[NSMutableArray alloc] init];
NSArray* stringObjects = [foundHits componentsSeparatedByString:#";"];
for(int i=0; i<[stringObjects count]; i++){
NSArray* strObj = [[stringObjects objectAtIndex:i] componentsSeparatedByString:#","];
if([strObj count]==3){
[objects addObject:strObj];
}
}
NSArray* orderedRes = [objects sortedArrayUsingComparator:^(id obj1, id obj2){
int x1 = [[obj1 objectAtIndex:0] intValue];
int x2 = [[obj2 objectAtIndex:0] intValue];
int y1 = [[obj1 objectAtIndex:1] intValue];
int y2 = [[obj2 objectAtIndex:1] intValue];
if(y1<y2){
return NSOrderedAscending;
} else if(y1>y2){
return NSOrderedDescending;
} else {
if(x1<x2){
return NSOrderedAscending;
} else if (x1>x2){
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
}];
[objects release];
NSLog(#"%#",currentQuery);
for(int i=0; i<[orderedRes count]; i++){
NSArray* currObj = [orderedRes objectAtIndex:i];
SearchResult* searchRes = [[SearchResult alloc] initWithChapterIndex:currentChapterIndex pageIndex:([[currObj objectAtIndex:1] intValue]/webView.bounds.size.height) hitIndex:0 neighboringText:[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"unescape('%#')", [currObj objectAtIndex:2]]] originatingQuery:currentQuery];
[results addObject:searchRes];
NSLog(#"%#",results);
[searchRes release];
}
//Print results
for(int i=0;i<[results count];i++)
{
SearchResult* hit = (SearchResult*)[results objectAtIndex:i];
NSLog(#"%#",hit.neighboringText);
}
[resultsTableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
if((currentChapterIndex+1)<[sharedManager.spineArray count]){
[self searchString:sharedManager.searchQuery inChapterAtIndex:(currentChapterIndex+1)];
} else {
fvc.searching= NO;
}
[[self resultsTableView] reloadData];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//- (void)dealloc
////{
//// self.resultsTableView = nil;
//// //[results release];
//// //[currentQuery release];
//// [super dealloc];
//}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
resultsTableView=[[UITableView alloc]init];
[resultsTableView setDelegate:self];
[resultsTableView setDataSource:self];
sharedManager=[Mymanager sharedManager];
// Do any additional setup after loading the view from its nib.
results = [[NSMutableArray alloc] init];
self.navigationItem.title=#"Search ";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem=backButton;
[[UINavigationBar appearance] setTitleTextAttributes: #{
UITextAttributeTextColor: [UIColor whiteColor],
UITextAttributeTextShadowColor: [UIColor lightGrayColor],
UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0.0f, 1.0f)],
UITextAttributeFont: [UIFont fontWithName:#"Trebuchet MS" size:15.0f]
}];
noMatchingSearch=[[NSArray alloc]initWithObjects:#"No Element Found", nil];
tableOfContents=[[NSMutableArray alloc]init];
for (id img in search.subviews)
{
if ([img isKindOfClass:NSClassFromString(#"UISearchBarBackground")])
{
[img removeFromSuperview];
}
}
tableOfContents=[sharedManager.List copy];
}
- (void)viewDidUnload
{
search = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
self.resultsTableView = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
MY SEARCH RESULTS
"<SearchResult: 0x113482c0>",
"<SearchResult: 0x11348a20>",
"<SearchResult: 0x88c0a50>"
The problem is with the search method before search the array is reinitialised and hence 0 returned in the resultArray and hence no value in tables
- (void) searchString:(NSString*)query{
self.results = [[NSMutableArray alloc] init];//Here it becomes 0!!
[resultsTableView reloadData];
currentQuery=sharedManager.searchQuery;
}
To make it right ,After the search is performed i believe
[self searchString:currentQuery inChapterAtIndex:0];
load the value in the result array and then reload table.
Make sure
in .h add
<UITableViewDataSource,UITableViewDelegate>
in nib
connect datasource and delegate[if via nib]