How to load array from web service for searching in uitextfield? - ios

I wish to send an array of say stationNames in a SOAP call .
Please help.
This code for manual input to array
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
possibleCompletionsForString:(NSString *)string
completionHandler:(void (^)(NSArray *))handler
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(queue, ^{
if(self.simulateLatency){
CGFloat seconds = arc4random_uniform(4)+arc4random_uniform(4); //normal distribution
NSLog(#"sleeping fetch of completions for %f", seconds);
sleep(seconds);
}
NSArray *completions;
if(self.testWithAutoCompleteObjectsInsteadOfStrings){
completions = [self allCountryObjects];
} else {
completions = [self allCountries];
}
handler(completions);
});
}
- (NSArray *)allCountryObjects
{
if(!self.countryObjects){
NSArray *countryNames = [self allCountries];
NSMutableArray *mutableCountries = [NSMutableArray new];
for(NSString *countryName in countryNames){
DEMOCustomAutoCompleteObject *country = [[DEMOCustomAutoCompleteObject alloc] initWithCountry:countryName];
[mutableCountries addObject:country];
}
[self setCountryObjects:[NSArray arrayWithArray:mutableCountries]];
}
return self.countryObjects;
}
- (NSArray *)allCountries
{
NSArray *countries =
#[
#"Item1",
#"Item2",
#"Item3",
#"Item4",
#"Item5",
#"Item6",
#"Item7",
#"Item8",
#"Item9",
];
return countries;
}
- (BOOL)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
shouldConfigureCell:(UITableViewCell *)cell
withAutoCompleteString:(NSString *)autocompleteString
withAttributedString:(NSAttributedString *)boldedString
forAutoCompleteObject:(id<MLPAutoCompletionObject>)autocompleteObject
forRowAtIndexPath:(NSIndexPath *)indexPath;
//This is your chance to customize an autocomplete tableview cell before it appears
in the autocomplete tableview
NSString *filename = [autocompleteString stringByAppendingString:#".png"];
filename = [filename stringByReplacingOccurrencesOfString:#" " withString:#"-"];
filename = [filename stringByReplacingOccurrencesOfString:#"&" withString:#"and"];
[cell.imageView setImage:[UIImage imageNamed:filename]];
return YES;
}
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
didSelectAutoCompleteString:(NSString *)selectedString
withAutoCompleteObject:(id<MLPAutoCompletionObject>)selectedObject
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(selectedObject){
NSLog(#"selected object from autocomplete menu %# with string %#", selectedObject,
[selectedObject autocompleteString]);
} else {
NSLog(#"selected string '%#' from autocomplete menu", selectedString);
}
}

Related

Messages deleted in chat room re-appear after re-enter the chat room

This below code is fired when I press delete button after selecting messages I want to delete in chat room.
- (void)deleteButtonPressed:(id)sender {
if (arrayToDelete.count) {
for (NSString *str in arrayToDelete) {
NSLog(#"msgID --> %#",str);
[self.chatModel.dataSource removeObject:str]; //??? Remove data from the screen
[[FMDBManager sharedInstance] deleteMessageByMessageId:str]; //??? Delete data from database
}
[arrayToDelete removeAllObjects];
[self.chatTableView reloadData];
}
}
This line successfully removes selected messages from the chat room.
[self.chatModel.dataSource removeObject:str]; //??? Remove data from the screen
When I go out the chat room and re-enter, those messages still exist, so I have this line below.
[[FMDBManager sharedInstance] deleteMessageByMessageId:str]; //??? Delete data from database
I think the above line should delete those selected messages from the database but when I re-enter the chat room I still see those messages. Here below are related code to that.
- (void)deleteMessageByMessageId:(NSString *)messageId {
FMDatabase *db = [self getterDataBase];
[db open];
NSString *sqlString = [NSString stringWithFormat:#"DELETE FROM message WHERE messageId = '%#'",messageId];
BOOL status = [db executeUpdate:sqlString];
NSLog(#"Delete MessageById:%# Status:%d",messageId,status);
[db close];
}
I've found that when chat room calls viewDidLoad it will eventually call the method callBackGetChannelLogNew where server will sync-up data with chat room tableview and local database.
- (void)callBackGetChannelLogNew:(NSDictionary *)resultDataDic status:(enumAPI_STATUS)eAPI_STATUS {
if (isFirstTimeUpdate) {
}
if (eAPI_STATUS == API_STATUS_SUCCEE) {
NSString *readString=[NSString stringWithFormat:#"%#",resultDataDic[#"read_arr"]];
if ([readString isEqualToString:#""]) {
// NSLog(#"read_arr is empty");
}
else {
NSArray *read_arr=resultDataDic[#"read_arr"];
// Copy read_arr
self.readArray=[read_arr mutableCopy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
[self dealWithReadArray:read_arr];
});
}
NSArray *data = [resultDataDic objectForKey:#"msg"];
if (data.count > 0) {
apiHaveData = YES;
} else {
apiHaveData = NO;
self.loadIngView.hidden = YES;
isLoadingData = NO;
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
// Reverse order of data
NSArray* reversedArray = [[data reverseObjectEnumerator] allObjects];
NSMutableArray *messageFromOtherArray = [NSMutableArray new];
NSMutableArray *messageAllArray = [NSMutableArray new];
for (int i = 0; i < reversedArray.count; i++) {
NSDictionary *_dic = reversedArray[i];
NSString *fromId = [_dic objectForKey:#"fid"];
NSString *message = [NSString stringWithFormat:#"%#",[_dic objectForKey:#"say"]];
if ([ObjectManager getChatMessageKindWithString:message] == MessageTypeText) {
message = [ObjectManager decryptWithString:message];
}
NSString *messageId = [_dic objectForKey:#"mid"];
NSString *toId = [_dic objectForKey:#"tid"];
NSDateFormatter *_formatter = [[NSDateFormatter alloc] init];
_formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss.SSS";
NSDate *date_t = [NSDate dateWithTimeIntervalSince1970:[[_dic objectForKey:#"t"] doubleValue]/1000.0]; //換算成日期
NSString *stringDate = [_formatter stringFromDate:date_t];
NSString *sendDate = stringDate;
NSString *lid = _dic[#"lid"];
NSMutableDictionary *myDic = [NSMutableDictionary dictionaryWithObjectsAndKeys:
fromId,#"fromId",
message,#"message",
messageId,#"messageId",
sendDate,#"sendDate",
toId,#"toId",
lid,#"lid",
nil];
NSString *isRead;
if (_chatRoomType == ChatRoomTypePrivate) {
if ([_dic[#"r"] intValue]) {
isRead = #"1";
myDic[#"isRead"] = isRead;
lastReadMessageId = [NSString stringWithFormat:#"%#",messageId];
}
}
if (i == 0) {
if (lidForAPI != [_dic[#"lid"] intValue]) {
lidForAPI = [_dic[#"lid"] intValue];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
apiHaveData = NO;
self.loadIngView.hidden = YES;
isLoadingData = NO;
});
return ;
}
}
if (![myDic[#"fromId"] isEqualToString:[User sharedUser].account]) {
[messageFromOtherArray addObject:myDic];
}
if (_chatRoomType == ChatRoomTypeGroup) {
[myDic setObject:#"1" forKey:#"isGroupMessage"];
}
[myDic setObject:#"1" forKey:#"did_I_Read"];
[messageAllArray addObject:myDic];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self setupViewWithMessageArray:messageAllArray]; //???? Here server sync-up data with tableview
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
if (_chatRoomType == ChatRoomTypePrivate) {
if (messageFromOtherArray.count > 0 && isUplaodLastRead == NO) {
isUplaodLastRead = YES;
NSDictionary *lastReadMsgDic = messageFromOtherArray.lastObject;
[self callMsgReadAPI:lastReadMsgDic];
}
} else {
if (messageAllArray.count > 0 && isUplaodLastRead == NO) {
isUplaodLastRead = YES;
NSDictionary *lastReadMsgDic = messageAllArray.lastObject;
[self callMsgReadAPI:lastReadMsgDic];
}
}
self.chatModel.channelTopic = _topic;
NSArray *read_arr=resultDataDic[#"read_arr"];
[self dealMySendMessageReadedWithReadArray:read_arr AndMessageArray:messageAllArray];
[self saveMessageWithArray:messageAllArray]; //???? Here server sync-up data with local db
});
});
}
}
This lines will sync-up data from server to tableview
dispatch_async(dispatch_get_main_queue(), ^{
[self setupViewWithMessageArray:messageAllArray]; //???? Here server sync-up data with tableview
});
Here below is the method setupViewWithMessageArray
- (void)setupViewWithMessageArray:(NSArray *)messageAllArray {
if (!isFirstTimeUpdate) {
isFirstTimeUpdate = YES;
self.chatModel.dataSource = nil;
[self.chatTableView reloadData];
self.chatModel.dataSource = [[NSMutableArray alloc] init];
[self addMessageWithArray:messageAllArray];
[self.chatTableView reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.chatModel.dataSource.count-1 inSection:0];
[self.chatTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
} else {
[self addMessageWithArray:messageAllArray];
[self reloadTableViewWithoutMove];
}
self.loadIngView.hidden = YES;
isLoadingData = NO;
if (_chatRoomType == ChatRoomTypePrivate) {
if (lastReadMessageId) {
[self.chatModel setPrivateChatListAllReadFormMessageId:lastReadMessageId];
}
}
}
This line will sync-up data from server to local db
[self saveMessageWithArray:messageAllArray]; //???? Here server sync-up data with local db
Here below is the method saveMessageWithArray
- (void)saveMessageWithArray:(NSArray *)messageArray {
for (NSDictionary *myDic in messageArray) {
if (![[FMDBManager sharedInstance] didMessageExistWithMessageID:[myDic objectForKey:#"messageId"]]) {
[[FMDBManager sharedInstance] SaveMessage:myDic];
}
else {
NSString *mid=[NSString stringWithFormat:#"%#",myDic[#"messageId"]];
NSString *isRead = myDic[#"isReaed"];
if (isRead) {
[[FMDBManager sharedInstance] UpdateisReadWithMessageID:mid];
}
}
}
}
So I think now my question is how I can update messageAllArray with arrayToDelete before server sync-up?

hpple: is it possible to get text value like javascript textContent

Is it possible to get only all the text content of the child elements recursively in hpple. Any method in TFHppleElement class?
such as the javascript
document.getElementById("testdiv").textContent
I'm using this code to get all content of the news title
NSURL *newURL = [NSURL URLWithString:#"http://somesite"];
NSData *newsData = [NSData dataWithContentsOfURL: newURL];
TFHpple *newsParser = [TFHpple hppleWithHTMLData: newsData];
NSString *newsXpathQueryString = #"//div[#class='item column-1']";
NSArray *newsNodes = [newsParser searchWithXPathQuery: newsXpathQueryString];
NSMutableArray *newNews = [[NSMutableArray alloc] initWithCapacity: 0];
for (TFHppleElement *element in newsNodes)
{
News *news = [[News alloc] init];
[newNews addObject: news];
news.title = [[element content] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
news.photo_url = [element objectForKey:#"src"];
_allNews = newNews;
[self.tableView reloadData];
}
}
you can use
news.title = [[element firstChild]content] to get children elements content
I wanted something like this - a quick boiler plate code, it is not an elegant solution with static contents. Please let me know, how can this be improved :)
#pragma mark - Hpple XML parser
/* The documents contents lots of nested div, table, span, style etc. */
- (NSString *) extractDefinition
{
NSString *html = [self.webView stringByEvaluatingJavaScriptFromString: #"document.getElementById('innerframe').innerHTML"];
if ([Resources stringIsEmpty:html]) {
return nil;
}
return [self extractSubDiv:html];
}
- (NSString *)extractSubDiv:(NSString *)html
{
TFHpple *hppleParser = [TFHpple hppleWithHTMLData:[html dataUsingEncoding:NSUTF8StringEncoding]];
NSString * xpathQuery;
xpathQuery = #"//div[#id='columnboth']";
NSArray * defNodes = [hppleParser searchWithXPathQuery:xpathQuery];
NSString * text = nil;
if ([defNodes count] > 0) {
TFHppleElement * element = [defNodes objectAtIndex:0];
text = [self parseContents:element];
} else {
xpathQuery = #"//div[#id='columnsingle']";
defNodes = [hppleParser searchWithXPathQuery:xpathQuery];
if ([defNodes count] > 0) {
TFHppleElement * element = [defNodes objectAtIndex:0];
text = [self parseContents:element];
}
}
return text;
}
- (NSString *) parseContents:(TFHppleElement *)element {
NSArray * innhold = [element searchWithXPathQuery:#"//div[contains(#class,'articlecontents')]"];
return [self getTextFromArray:innhold];
}
static NSMutableString * contents;
- (NSString *) getTextFromArray:(NSArray *)hppleElments {
NSMutableString * text = [[NSMutableString new] autorelease];
contents = nil;
contents = [[NSMutableString new] autorelease];
for (TFHppleElement * e in hppleElments) {
[text appendFormat:#"%# ", [self getText:e]];
}
return text;
}
/* Here are more nested div and then span for text. */
- (NSString *) getText:(TFHppleElement *)element
{
if ([element isTextNode]) {
[contents appendFormat:#" %#", element.content];
}
for (TFHppleElement * e in element.children) {
[self getText:e];
}
return contents;
}

Save UICollectionViewCell progress state

I've already asked the same question about saving pressed button state and I thought that I should do in the same way to save progress state on cells but my tries are unsuccessful.
What I'm doing now: I select some UICollectionViewCell's and then press "download" button and then downolad action starts. Every cell I selected shows UIProgressView and everything is ok untill I scroll my UICollectionView up or down. When I do it another cells have progress view too but they mustn't! I know that I must save indexPath of selected cells in NSMutableArray and then in cellForItemAtIndexPath check if current cell indexPath is in my array and then show or hide my cell's subviews. I do that but it only works with cell selection! What should I do to save progress view state on each cell this progress really there?
Here is my code:
In cellForItemAtIndexPath:
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ([selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
cell.selectedBG.hidden = NO;
cell.selectedImg.hidden = NO;
}
else
{
cell.selectedBG.hidden = YES;
cell.selectedImg.hidden = YES;
cell.progressView.hidden = YES;
}
In didSelectItemAtIndexPath:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
...
// Add the selected item into the array
[selectedIds addObject:selectedId];
[selectedVideos addObject:selectedVideo];
AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ( ![selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[selecedCellsArray addObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = NO;
collectionCell.selectedImg.hidden = NO;
[collectionCell setSelected:YES];
}
}
}
In didDeselectItemAtIndexPath:
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
...
// Delete the selected item from the array
[selectedIds removeObject:selectedId];
[selectedVideos removeObject:selectedVideo];
AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ( [selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[selecedCellsArray removeObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = YES;
collectionCell.selectedImg.hidden = YES;
[collectionCell setSelected:NO];
}
}
And this is how I show my progress:
-(NSString *)progress:(long long )val1 : (long long )val2 : (AVMVideoCell *)cell : (NSString *)name : (NSIndexPath *)path{
float progress = ((float)val1) / val2;
NSString *prog = [[NSNumber numberWithFloat:progress*100] stringValue];
if (prog != nil){
if(cell.isSelected){
cell.selectedImg.hidden = YES;
cell.progressView.hidden = NO;
}
}
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)path.row];
if ( [selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]])
{
[cell.progressView setProgress:progress animated:YES];
}
if([prog intValue]==100){
cell.progressView.hidden = YES;
}
return prog;
}
EDIT: AVMVideoCell.m
#import "AVMVideoCell.h"
#implementation AVMVideoCell
{
NSString *fullUrl;
}
#synthesize imageView;
#synthesize selectedBG;
#synthesize progressLabel;
#synthesize progressView;
#synthesize selectedImg;
#synthesize progLayer;
-(void) setVideo:(AVMDataStore *)video {
if(_video != video) {
_video = video;
}
NSString *durString = [NSString stringWithFormat:#"%#",[self timeFormatted:_video.duration]];
if((_video.filePreview != nil) && ![_video.filePreview isEqualToString:#""]){
fullUrl = [NSString stringWithFormat:#"http://example.com%#",_video.filePreview];
}
NSURL *imgURL = [NSURL URLWithString:fullUrl];
[self.imageView setImageWithURL:imgURL
placeholderImage:[UIImage imageNamed:#"yesterday.png"] options:0 usingActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
self.duration.text = durString;
}
- (NSString *)timeFormatted:(int)totalSeconds
{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return [NSString stringWithFormat:#"%02d:%02d:%02d",hours, minutes, seconds];
}
#end
EDIT 2: Explanation about progress
My progressView is not an IBOutlet it's a #property (nonatomic,strong) UIProgressView *progressView; (AVMVideoCell.h)
I allocate and initialize it in cellForItemAtIndexPath:
cell.progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0,0, 150.0f, 1.0f)];
cell.progressView.trackTintColor = [UIColor colorWithWhite:255 alpha:0.5f];
cell.progressView.progressTintColor = [UIColor whiteColor];
[cell.progLayer addSubview:cell.progressView];
cell.progressView.hidden = YES;
cell.progressView.tag = indexPath.row+500;
This is where I call progress change showing:
-(void)downloadStart:(NSString*)fileUrl : (NSString*)name : (AVMVideoCell *) cell : (NSIndexPath *)path{
NSURL *URL = [NSURL URLWithString:fileUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSString *fileName = [NSString stringWithFormat:#"%#.mp4",name]; //set full file name to save
AFHTTPRequestOperation *downloadRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request]; //create download request
[downloadRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSData *data = [[NSData alloc] initWithData:responseObject];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *pathToFile = [NSString stringWithFormat:#"%#/%#", [paths firstObject],fileName]; // path to 'Documents'
NSString *pathOfFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:pathOfFile append:NO];
BOOL success = [data writeToFile:pathToFile atomically:YES];
if(success){
[self checkIfExists:name : cell :path];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"file downloading error : %#", [error localizedDescription]);
UIAlertView * alert=[[UIAlertView alloc]initWithTitle:#"Error" message:[NSString stringWithFormat:#"%#",error] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil ];
[alert show];
cell.progressView.hidden = YES;
}];
// Step 5: begin asynchronous download
[downloadRequest start];
[downloadRequest setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
[self progress:totalBytesRead :totalBytesExpectedToRead :cell :name : path]; //here I pass val1 and val 2
}];
}
When I select an items in collection view, I gather their model's objects, get each id and make array of urls, then in for..in loop i pass urls one by one and then start async download. You can see how I download and call progress method above.
I need to know if you have a reuse issue or a model issue.
So first try this :
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
...
if (![selectedIds.containsObject:selectedId])
{
// Add the selected item into the array
[selectedIds addObject:selectedId];
[selectedVideos addObject:selectedVideo];
AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ( ![selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[selecedCellsArray addObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = NO;
collectionCell.selectedImg.hidden = NO;
[collectionCell setSelected:YES];
}
}
else {
// Delete the selected item from the array
[selectedIds removeObject:selectedId];
[selectedVideos removeObject:selectedVideo];
AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ( [selecedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[selecedCellsArray removeObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = YES;
collectionCell.selectedImg.hidden = YES;
[collectionCell setSelected:NO];
}
}
and remove the didDeselect delegate.
Let me know what happens then.
EDIT :
Ok try this now:
// Lazy instantiation of the progressView
- (UIProgressView *)progressView
{
if (!_progressView)
{
_progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0,0, 150.0f, 1.0f)];
_progressView.trackTintColor = [UIColor colorWithWhite:255 alpha:0.5f];
_progressView.progressTintColor = [UIColor whiteColor];
_progressView.hidden = YES;
[self.contentView addSubview:_progressView];
}
return _progressView;
}
// Here we remove the progressView on reuse
-(void)prepareForReuse
{
[super prepareForReuse];
[self.progressView removeFromSuperview];
self.progressView = nil;
}
Also remove what you did with the progressView with in the cellForItemAtIndexPath method.
You can create class for cell's models, store these models in array in your viewController and use them to get/set all states from/for cells.
Something like this:
#interface CellModel : NSObject
#property(nonatomic) BOOL selected;
#property(nonatomic) NSUInteger progress;
#end
In viewController:
#interface MyViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic) NSArray* models;
#end

iOS mutable json

i am trying to do a radio app, i want to get the album art from itunes, am about to finish but i need some help here, i dont know how to make my json request take my metadata variables everytime the song change, here is my code in .m
#import "EDViewController.h"
#define STREAM_URL #"http://4893.live.streamtheworld.com:80/ROCK_FMAAC_SC"
#interface EDViewController ()
#end
#implementation EDViewController
- (void)viewDidLoad {
radio = [[Radio alloc] init:#""];
[radio connect:STREAM_URL withDelegate:self withGain:(1.0)];
playing = YES;
[super viewDidLoad];;
NSMutableString *urlString = [NSMutableString stringWithFormat:#"https://itunes.apple.com/search?term"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableDictionary *artwork = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSMutableArray *results = [artwork objectForKey:#"results"];
NSDictionary *album = [results objectAtIndex:0];
NSString *artalbum = [album objectForKey:#"artworkUrl100"];
NSURL *urlOne = [NSURL URLWithString:artalbum];
NSData *newData = [NSData dataWithContentsOfURL:urlOne];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRectMake(0, 69, 320, 325))];
[imageView setImage:[UIImage imageWithData:newData]];
[self.view addSubview:imageView];
UIImageView *imageView2 = [[UIImageView alloc] initWithFrame:(CGRectMake(95, 167, 130, 130))];
[imageView2 setImage:[UIImage imageWithData:newData]];
[self.view addSubview:imageView2];
}
- (IBAction)play {
[radio resume];
}
- (IBAction)stop {
[radio updatePlay:NO];
}
- (IBAction)pause {
[radio pause];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
- (void)uodateBuffering:(BOOL)value {
NSLog(#"delegate update buffering %d", value);
}
- (void)interruptRadio {
NSLog(#"delegate radio interrupted");
}
- (void)resumeInterruptRadio {
NSLog(#"delegate resume interrupted Radio");
}
- (void)networkChanged {
NSLog(#"delegate network changed");
}
- (void)connectProblem {
NSLog(#"delegate connection problem");
}
- (void)audioUnplugged {
NSLog(#"delegate audio unplugged");
}
- (void)metaTitleUpdated:(NSString *)title {
NSLog(#"delegate title updated to %#", title);
NSArray *chunks = [title componentsSeparatedByString:#";"];
if ([chunks count]) {
NSArray *streamTitle = [[chunks objectAtIndex:0] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"'-"]];
if ([streamTitle count] > 1) {
titleLabel.text = [streamTitle objectAtIndex:1];
}
NSArray *streamArtist = [[chunks objectAtIndex:0] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"'-"]];
if ([streamArtist count] > 1) {
test100.text = [streamArtist objectAtIndex:2];
}
}
}
#end
As you can see my metadata info is at the end of my code and my json request its almost at the top.`

I am getting an unauthorized error quickblox

I have the following code using quickblox.
Unfortunately, when I accessthe view controller, I get an "unAuthorized" error from quickblox API.
What am I doing wrong?
#import "QChatViewController.h"
#include "ChatMessageTableViewCell.h"
#interface QChatViewController ()
#end
#implementation QChatViewController
#synthesize opponent;
#synthesize currentRoom;
#synthesize messages;
#synthesize toolBar;
#synthesize sendMessageField;
#synthesize sendMessageButton;
#synthesize tableView;
#pragma mark -
#pragma mark View controller's lifecycle
- (id) initWithStartup: (NSDictionary *) _startup investor: (NSDictionary *) _investor chat_id: (NSInteger) _chat_id chat_name: (NSString *) _name
{
self = [self initWithNibName: #"QChatViewController" bundle: nil];
if(self)
{
startup = _startup;
investor = _investor;
startup_id = 0;
investor_id = 0;
if ([startup objectForKey: #"id"] &&
[startup objectForKey: #"id"] != (id)[NSNull null])
{
startup_id = [[startup objectForKey: #"id"] intValue];
}
if ([investor objectForKey: #"id"] &&
[investor objectForKey: #"id"] != (id)[NSNull null])
{
investor_id = [[investor objectForKey: #"id"] intValue];
}
past = 0;
chat_id = _chat_id;
self.title = _name;
self.title = #"Chat";
UIButton * button4 = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage * btnImage = [UIImage imageNamed: #"chatrightbtn.png"];
[button4 setFrame:CGRectMake(-90.0f, 0.0f, btnImage.size.width, btnImage.size.height)];
[button4 addTarget:self action:#selector(showSheet:) forControlEvents:UIControlEventTouchUpInside];
[button4 setImage: btnImage forState:UIControlStateNormal];
UIBarButtonItem *random1 = [[UIBarButtonItem alloc] initWithCustomView:button4];
self.navigationItem.rightBarButtonItem = random1;
self.navigationItem.leftBarButtonItem.title = #"";
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
QBASessionCreationRequest *extendedAuthRequest = [QBASessionCreationRequest request];
extendedAuthRequest.userLogin = #"testjk";
extendedAuthRequest.userPassword = #"jerry";
[QBAuth createSessionWithExtendedRequest:extendedAuthRequest delegate:self];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = NO;
if(chat_id >= 1) {
NSString * roomName = [NSString stringWithFormat: #"%d", chat_id];
[[QBChat instance] createOrJoinRoomWithName: roomName membersOnly:YES persistent:NO];
}
messages = [[NSMutableArray alloc] init];
}
-(void) chatDidLogin{
// You have successfully signed in to QuickBlox Chat
}
- (void)completedWithResult:(Result *)result{
// Create session result
if(result.success && [result isKindOfClass:QBAAuthSessionCreationResult.class]){
// You have successfully created the session
QBAAuthSessionCreationResult *res = (QBAAuthSessionCreationResult *)result;
// Sign In to QuickBlox Chat
QBUUser *currentUser = [QBUUser user];
currentUser.ID = res.session.userID; // your current user's ID
currentUser.password = #"jerry"; // your current user's password
// set Chat delegate
[QBChat instance].delegate = self;
// login to Chat
[[QBChat instance] loginWithUser:currentUser];
}
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
// leave room
if(self.currentRoom){
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
// back button was pressed.
[[QBChat instance] leaveRoom:self.currentRoom];
[[DataManager shared].rooms removeObject:self.currentRoom];
}
}
}
- (void)viewDidUnload{
[self setToolBar:nil];
[self setSendMessageField:nil];
[self setSendMessageButton:nil];
[self setTableView:nil];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
}
- (IBAction)sendMessage:(id)sender {
if(self.sendMessageField.text.length == 0){
return;
}
if(chat_id == 0)
{
NSString * sid = [NSString stringWithFormat: #"%d", startup_id];
NSString * iid = [NSString stringWithFormat: #"%d", investor_id];
NSString * pasts = [NSString stringWithFormat: #"%d", past];
NSString * chat_ids = [NSString stringWithFormat: #"%d", chat_id];
NSString * path_str = [NSString stringWithFormat: #"chats/?format=json"];
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:
sid, #"startup",
iid, #"investor",
pasts, #"past",
chat_ids, #"conversation_id",
#"avv7ejtaegxxk2wzgnymsj8xtm2tk9s4xgp6854r6dqn8bk6jjwux4g9dh9b", #"apikey",
nil];
[[API sharedInstance] postcommandWithParams:params
path: path_str
onCompletion:^(NSDictionary *json)
{
if(chat_id == 0)
{
if ([json objectForKey: #"id"] &&
[json objectForKey: #"id"] != (id)[NSNull null])
{
chat_id = [[json objectForKey: #"id"] intValue];
if(chat_id >= 1) {
NSString * roomName = [NSString stringWithFormat: #"%d", chat_id];
[[QBChat instance] createOrJoinRoomWithName: roomName membersOnly:YES persistent:NO];
}
[[QBChat instance] sendMessage:self.sendMessageField.text toRoom:self.currentRoom];
// reload table
[self.tableView reloadData];
// hide keyboard & clean text field
[self.sendMessageField resignFirstResponder];
[self.sendMessageField setText:nil];
}
}
}];
}
else
{
[[QBChat instance] sendMessage:self.sendMessageField.text toRoom:self.currentRoom];
// reload table
[self.tableView reloadData];
// hide keyboard & clean text field
[self.sendMessageField resignFirstResponder];
[self.sendMessageField setText:nil];
}
}
-(void)keyboardShow{
CGRect rectFild = self.sendMessageField.frame;
rectFild.origin.y -= 215;
CGRect rectButton = self.sendMessageButton.frame;
rectButton.origin.y -= 215;
[UIView animateWithDuration:0.25f
animations:^{
[self.sendMessageField setFrame:rectFild];
[self.sendMessageButton setFrame:rectButton];
}
];
}
-(void)keyboardHide{
CGRect rectFild = self.sendMessageField.frame;
rectFild.origin.y += 215;
CGRect rectButton = self.sendMessageButton.frame;
rectButton.origin.y += 215;
[UIView animateWithDuration:0.25f
animations:^{
[self.sendMessageField setFrame:rectFild];
[self.sendMessageButton setFrame:rectButton];
}
];
}
#pragma mark -
#pragma mark TextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField{
[self keyboardShow];
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
[self keyboardHide];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField setText:nil];
[textField resignFirstResponder];
return YES;
}
#pragma mark -
#pragma mark TableViewDataSource & TableViewDelegate
static CGFloat padding = 20.0;
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"MessageCellIdentifier";
// Create cell
ChatMessageTableViewCell *cell = (ChatMessageTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ChatMessageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.userInteractionEnabled = NO;
// Message
QBChatMessage *messageBody = [messages objectAtIndex:[indexPath row]];
// set message's text
NSString *message = [messageBody text];
cell.message.text = message;
// message's datetime
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat: #"yyyy-mm-dd HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"..."]];
NSString *time = [formatter stringFromDate:messageBody.datetime];
CGSize textSize = { 260.0, 10000.0 };
CGSize size = [message sizeWithFont:[UIFont boldSystemFontOfSize:13]
constrainedToSize:textSize
lineBreakMode:UILineBreakModeWordWrap];
size.width += (padding/2);
// Left/Right bubble
UIImage *bgImage = nil;
if ([[[DataManager shared] currentUser] ID] == messageBody.senderID || self.currentRoom) {
bgImage = [[UIImage imageNamed:#"orange.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
[cell.message setFrame:CGRectMake(padding, padding*2, size.width+padding, size.height+padding)];
[cell.backgroundImageView setFrame:CGRectMake( cell.message.frame.origin.x - padding/2,
cell.message.frame.origin.y - padding/2,
size.width+padding,
size.height+padding)];
cell.date.textAlignment = UITextAlignmentLeft;
cell.backgroundImageView.image = bgImage;
if(self.currentRoom){
cell.date.text = [NSString stringWithFormat:#"%d %#", messageBody.senderID, time];
}else{
cell.date.text = [NSString stringWithFormat:#"%# %#", [[[DataManager shared] currentUser] login], time];
}
} else {
bgImage = [[UIImage imageNamed:#"aqua.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
[cell.message setFrame:CGRectMake(320 - size.width - padding,
padding*2,
size.width+padding,
size.height+padding)];
[cell.backgroundImageView setFrame:CGRectMake(cell.message.frame.origin.x - padding/2,
cell.message.frame.origin.y - padding/2,
size.width+padding,
size.height+padding)];
cell.date.textAlignment = UITextAlignmentRight;
cell.backgroundImageView.image = bgImage;
cell.date.text = [NSString stringWithFormat:#"%# %#", self.opponent.login, time];
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.messages count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
QBChatMessage *chatMessage = (QBChatMessage *)[messages objectAtIndex:indexPath.row];
NSString *text = chatMessage.text;
CGSize textSize = { 260.0, 10000.0 };
CGSize size = [text sizeWithFont:[UIFont boldSystemFontOfSize:13]
constrainedToSize:textSize
lineBreakMode:UILineBreakModeWordWrap];
size.height += padding;
return size.height+padding+5;
}
#pragma mark -
#pragma mark QBChatDelegate
// Did receive 1-1 message
- (void)chatDidReceiveMessage:(QBChatMessage *)message{
[self.messages addObject:message];
// save message to cache if this 1-1 chat
if (self.opponent) {
[[DataManager shared] saveMessage:[NSKeyedArchiver archivedDataWithRootObject:messages]
toHistoryWithOpponentID:self.opponent.ID];
}
// reload table
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[messages count]-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
// Did receive message in room
- (void)chatRoomDidReceiveMessage:(QBChatMessage *)message fromRoom:(NSString *)roomName{
// save message
[self.messages addObject:message];
// reload table
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[messages count]-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
// Fired when you did leave room
- (void)chatRoomDidLeave:(NSString *)roomName{
NSLog(#"Chat Controller chatRoomDidLeave");
}
// Called in case changing occupant
- (void)chatRoomDidChangeOnlineUsers:(NSArray *)onlineUsers room:(NSString *)roomName{
NSLog(#"chatRoomDidChangeOnlineUsers %#, %#",roomName, onlineUsers);
}
- (void)chatRoomDidEnter:(QBChatRoom *)room{
NSLog(#"Private room %# was created", room.name);
// You have to retain created room if this is temporary room. In other cases room will be destroyed and all occupants will be disconnected from room
self.currentRoom = room;
// Add users to this room
NSInteger user_id = [[[[API sharedInstance] user] objectForKey: #"id"] intValue];
NSNumber *me = [NSNumber numberWithInt: user_id];
NSArray *users = [NSArray arrayWithObjects: me, nil];
[[QBChat instance] addUsers:users toRoom:room];
}
#end
I'm not sure that you have user with these credentials
extendedAuthRequest.userLogin = #"testjk";
extendedAuthRequest.userPassword = #"jerry";
I first check user exist or not modified your code like this...
//your code
.....
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
//Create extended session request with user authorization
QBASessionCreationRequest *extendedAuthRequest = [QBASessionCreationRequest request];
//Check user exist or not
if(self.currentQBUser){
extendedAuthRequest.userLogin = #"testjk";
extendedAuthRequest.userPassword = #"testjk";
}
[QBAuth createSessionWithExtendedRequest:extendedAuthRequest delegate:self];
}
........
- (void)completedWithResult:(Result *)result{
// Create session result
if(result.success && [result isKindOfClass:QBAAuthSessionCreationResult.class]){
// Register new user
self.currentQBUser = [[QBUUser alloc] init];
user.fullName = #"Your Name";
user.login = #"testjk";
user.password = #"testjk";
user.tags = [NSMutableArray arrayWithObject:#"Chat"];
// Create user
[QBUsers signUp:user delegate:self];
// You have successfully created the session
QBAAuthSessionCreationResult *res = (QBAAuthSessionCreationResult *)result;
} else if([result isKindOfClass:[QBUUserLogInResult class]]){
if(result.success){
QBUUserLogInResult *res = (QBUUserLogInResult *)result;
//Now login to chat
// Sign In to QuickBlox Chat
QBUUser *currentUser = res.user;
currentUser.ID = #"testjk; // your current user's ID
currentUser.password = #"testjk"; // same as user id
// set Chat delegate
[QBChat instance].delegate = self;
// login to Chat
[[QBChat instance] loginWithUser:currentUser];
}
}
if (result.errors.count && (401 != result.status))
{
NSLog(#"QBErrors: %#",result.errors);
}
}
I met the same problem here. And i gave the way i made it.
error unauthorized is the user.login or user.password.
user.login can not be email address but your login username. these i do not know why.
user.password is the email address/username password.
check these informations in your User list at QuickBlox Dashboard
Hope these instructions will help.
use quickblox.min.js
var QBApp = {
appId: 123,
authKey: 'dfdgfd44444',
authSecret: 'dffdgfdg455445'
};
$(document).ready(function () {
QB.init(QBApp.appId, QBApp.authKey, QBApp.authSecret);
QB.createSession(function (err, result) {
console.log('Session create callback', err, result);
});
})
function addUser() {
var pwd, ctr, data;
ctr = document.getElementById(myForm.password);
pwd = ctr.value;
var params = { 'login': 'Rajesh', 'password': 'Pass#123' };
alert(params)
QB.users.create(params, function (err, user) {
debugger;
if (user) {
alert('Done')
//$('#output_place').val(JSON.stringify(user));
} else {
alert('Error')
//$('#output_place').val(JSON.stringify(err));
}
})}

Resources