So what can I replace TTTableTextItem with? - iphone

So here's what I'm working with.
I'm trying to get rid of the Three20 framework...but I'm not sure what I should replace this specifically with:
NSMutableArray *selectedPeople = [[NSMutableArray alloc] init];
NSArray *cells = [textField cells];
for (TTTableTextItem *cell in cells) {
NSDictionary *person = [textField.dataSource contactInfoAtIndex:[cell.URL integerValue]];
[selectedPeople addObject:person];
[AppPreferences incrementContactUsage:[[person objectForKey:#"abId"] intValue]];
}
I've got a textfield that is implemented similar to the Token field view in the Messages app. (using JSTokenField... I've replaced TTPickerView with that).
I'm fairly new to the iOS scene, and I'm working on an old project (trying to get it out of the gutter).
Thank you for the help in advance.

Related

grab text from NSMutableArray tableview cell

I don't understand why the code isn't working, and nothing I found seems to be working. So I've come here for help. Ultimately, I want to be able to send my link to Safari whenever I click on the "View" button, and I want the link to be copied whenever I click on the "Copy" button.
Here's the code (under " - (void)viewDidLoad "):
NSMutableArray *sites = [[NSMutableArray alloc] initWithObjects:#"http://www.apple.com/", #"http://www.youtube.com/", #"http://maps.google.com/", #"http://ww.google.com/", #"http://www.stackoverflow.com/", nil];
self.cloudsendList = sites;
Here is the code (under " - (IBAction) touchUpInsideAction:(UIButton*)button "):
NSIndexPath* indexPath = [tableView indexPathForCell:sideSwipeCell];
NSUInteger index = [buttons indexOfObject:button];
NSDictionary* buttonInfo = [buttonData objectAtIndex:index];
if ([[buttonInfo objectForKey:#"title"] isEqualToString:#"View"]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat: #"%#", indexPath.row]]];
} else if ([[buttonInfo objectForKey:#"title"]isEqualToString:#"Copy"]) {
NSString *message = indexPath.row;
[UIPasteboard generalPasteboard].string = message;
Just to note, I am able to see the NSMutableArray data on each cell, I just can't grab it. I've also tried to insert "cloudsendList indexPath.row" instead of just "indexPath.row", but it didn't work. I hope this gives you enough information, and any bit of help would be really appreciated. Also, I apologize if I sound kind of noobish; I'm still sort of new to Objective-C programming. Thanks! :)
indexPath.row is an NSInteger, not the text at that location. This means your NSString *message is getting the integer value of the row you are on (0, 1, 2...). Try using that location as an index when pulling from your sites/cloudsendList array.
Ex.
NSString *message = [cloudsendList objectAtIndex:indexPath.row];
UPDATE:
To open the browser, use the same concept.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat: #"%#", [cloudsendList objectAtIndex:indexPath.row]]]];

NSDictionary to NSArray, will not display properly?

I have a signature page, were the user can sign their name.
It needs to then be saved to NSDictionary, but i want to call a List of the keys to be text in a TableView for each row or cell.
so:
"viewImage = saved as object to key:Random Number"
That parts somewhat easy, the hard part is when i call it on the other Page to the TableView.
It Exits the App with Error"SIGABRT". Now all my Delegates are in place and working...i believe.
now heres some example code:
FirstPage.m
UIImagePNGRepresentation(viewImage);
NSMutableArray *innerArray = [[NSMutableArray array]init];
[innerArray addObject:viewImage];
[SignatureSave setObject:innerArray forKey:#"5599"];
simple Enough, but doesnt give me an error.
SecondPage.m
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FirstPage *appShare = (FirstPage *)[[UIApplication sharedApplication] delegate];
NSArray *dataDuplicate = [[NSArray alloc]init ];
dataDuplicate = [appShare.SignatureSave allKeysForObject:#"innerArray"];
static NSString *CellIdentifier = #"Cell";
NSLog(#"%#",dataDuplicate);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero]autorelease];
}
if (dataDuplicate != nil) {
cell.textLabel.text = [dataDuplicate objectAtIndex:indexPath.row];
}
else
{
UIAlertView *CellAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Error Loading content, Try Again Later." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[CellAlert show];
[CellAlert release];
}
return cell;
}
#end
Now, How do i get the viewImage to save to the NSDictionary, to be able to call it on the SecondPage and display the name of the objects in the TableVIew?
I really don't understand whats your problem exactly.
first of all, is your dictionary a retained object?
//FirstPage.h
#property (nonatomic, retain) NSDictionary *SignatureSave;
//FirstPage.m
#synthesize SignatureSave;
…
UIImagePNGRepresentation(viewImage);
NSMutableArray *innerArray = [NSMutableArray array]; // using "array" is equivalent to alloc-init-autorelease
[innerArray addObject:viewImage];
[self.SignatureSave setObject:innerArray forKey:#"5599"];
// OR setting the array directly:
UIImagePNGRepresentation(viewImage);
NSArray *innerArray = [NSArray arrayWithObject:viewImage];
[self.SignatureSave setObject:innerArray forKey:#"5599"];
// OR even setting the image directly to the dictionary:
UIImagePNGRepresentation(viewImage);
[self.SignatureSave setObject:viewImage forKey:#"5599"];
now if you access the object by writing self. in front it will call the retain and your object will stay alive. Otherwise it would be autoreleased at the end of the method. This will fix the problem that your dictionary is maybe not present/available at table view creation and you don't have to use a singleton.
what are you trying to access with this code?
FirstPage *appShare = (FirstPage *)[[UIApplication sharedApplication] delegate];
with [[UIApplication sharedApplication] delegate] you get your application delegate (obviously). These are the MyAppNameAppDelegate files but you treat it as a FirstPage class.
Just NSLog() to check you get the right class, the one you expect.
NSLog(#"%#", [[[UIApplication sharedApplication] delegate] class]);
here you have a potential leak, you alloc-init but never release it:
NSArray *dataDuplicate = [[NSArray alloc]init ];
dataDuplicate = [appShare.SignatureSave allKeysForObject:#"innerArray"];
furthermore you can simplify it (will be autoreleased):
NSArray *dataDuplicate = [appShare.SignatureSave allKeysForObject:#"innerArray"];
and here you have another issue.
Why do you call all keys for the object #"innerArray"?
you don't have such an object and it's in many more cases wrong. innerArray was your previously named array in FirstPage.m but it is only for you as a developer to remember the variable better. After compilation it will have a cryptic name anyway. You could access your key #"5599" if you like but I don't think you want this. In your case you want to access all keys of the dictionary so simply call:
NSArray *dataDuplicate = [appShare.SignatureSave allKeys];
now you will have an array with all keys of your dictionary and you can access them like you do with objectAtIndex:.
NSString *keyName = [dataDuplicate objectAtIndex:indexPath.row];
cell.textLabel.text = keyName;
id theObject = [appShare.SignatureSave objectForKey:keyName]; // for example the image
Tell me if this solves your problems or tell me how I misunderstood your question.
I found the answer to this to be quit simple actually,
I ended up going with the Singleton Method instead of the Global Variable Method.
Now the Singleton Method looks terrifying but its quit simple, See here.
The main difference i noticed from the singleton method to the global method is,
Global method takes a lot of converting and re-converting.
Though the Singleton Method is working with a single object over many pages or classes.
Now i hope this will better assist people in the future also!

Objective-C/iOS : Message sent to deallocated instance

This is my first post on stackoverflow.com so please be kind (rewind) ;)
I have a navigation based application whose purpose is to display blog posts (title) in a Table View (with JSON).
The problem I ran into occurred when a cell got out of the screen and then back in.
I was getting a EXC_BAD_ACCESS (because I sent a message to a deallocated instance), so I struggled to understand where it came from and I finally found a solution. But the fact is I don't exactly understand how the problem occurs. That's why I need someone to enlighten me, I think this is fundamental understanding !
When the connection to the JSON web service has finished loading, I parse the JSON code to obtain a list of blog posts (recentPosts), then I create a BlogArticle object for each post (blogArticle), store it in a MutableArray iVar (allEntries) and insert a row in the Table View :
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSError *error;
SBJsonParser *json = [[SBJsonParser new] autorelease];
NSDictionary *recentPostsData = [json objectWithString:responseString error:&error];
[responseString release];
NSArray *recentPosts = [recentPostsData objectForKey:#"posts"];
int i = 0;
for (NSDictionary *post in recentPosts) {
BlogArticle *blogArticle = [[BlogArticle alloc] initWithDictionary:post];
[allEntries insertObject:blogArticle atIndex:i];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
i++;
}
}
Here's the initialisation of the BlogArticle object which turned to be the origin of the problem :
- (id)initWithDictionary:(NSDictionary *)article
{
if (self = [super init])
{
// title = [[[article valueForKey:#"title"] gtm_stringByUnescapingFromHTML] copy];
// title = [[NSString alloc] initWithString:[[article valueForKey:#"title"] gtm_stringByUnescapingFromHTML]];
title = [[article valueForKey:#"title"] gtm_stringByUnescapingFromHTML];
}
return self;
}
So every Objective-C programmer who isn't as noobish as me is able to tell that title is never allocated before being assigned. If I uncomment one of the two lines above it will work. The program crashes exactly when I try to initialize a cell with that title variable, here :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(#"indexPath.row = %i", indexPath.row);
// Configure the cell.
BlogArticle *article = [allEntries objectAtIndex:indexPath.row];
cell.textLabel.text = article.title;
return cell;
}
Now, what I need to understand is why it does compile/work without allocating the iVar and where exactly it causes trouble (or where exactly the content of title is released causing the program to crash).
Any good resource (noob friendly) about memory management in iOS environment would be much appreciated.
Thanks in advance :)
This line
title = [[article valueForKey:#"title"] gtm_stringByUnescapingFromHTML];
is allocating an autoreleased string. Essentially, think of it that an autoreleased string will get released at the end of the method (though it can last longer, it's useful to think of it that way).
You know the string is autoreleased because the name of the method gtm_stringByUnescapingFromHTML does not start with alloc, new, copy or mutableCopy.
You can add retain to this to stop it getting autoreleased:
title = [[[article valueForKey:#"title"] gtm_stringByUnescapingFromHTML] retain];
Now you own the string, and it will not get released until you say so.
The best summary I know of is Apple's own documentation here.
Well, the problem is, that you have to initialize your object, if you want to manage the memory of it on your own. Why should you manage now the memory of title?
Quite simple:
Every object reference, that is stored in an Array, Set, Dictionary etc. is managed by the Array, Dictionary and Set.
If you now just use this reference (by writing: "title = ...") in your cell, you will add the reference also to the cell. And now the cell is also responsible for the object-reference. So if the tableView wants to release your cells, which will happen from time to time to save memory, the cell will release your title-object. And this would cause the NSDitionary to be quite sad, since the NSDictionary wants to take care about the objects stored within itself.
So you could write the following in the tableView-method:
cell.textLabel.text = [article.title retain];
Or the commented lines of your own method.
That means, you will "raise" the storage-level of your object up and if it gets released, the storage level itself will be decreased by one.
If the storage-level will reach zero, it will be completely released (that should happen, if your tablecell is released AND your NSDIctionary)
I hope i could help you a bit :)

addObject to NSMutableArray not working for iPhone App

There have been a few threads on this topic but none have been able to solve my problem. Essentially I am trying to add a custom object to an NSMutableArray and it doesn't seem to be adding. I don't get any errors but I get a warning saying that my array is an "unused variable" so it looks like it is not getting used. See code below. Any help is appreciated!
Here is the initialization in the app delegate (on run time it says this array is not being used):
NSMutableArray *organArray = [[NSMutableArray alloc] init];
Here is my object class organ.m (I am importing the app delegate, the rootviewcontroller and the organ.h file)
Organ *organObj = [[Organ alloc] initWithPrimaryKey:primaryKey];
organObj.organName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)];
organObj.isDirty = NO;
[appDelegate.organArray addObject: organObj];
[organObj release];
I know the organObj.organName is getting the correct values from my sqlite db because I can output them to the console. They just don't seem to be getting added to the array and the fact that it says the array is not being used means something is wrong.
Thanks in advance
Just a guess but if organArray is intended to be a member of your app delegate, you are creating a new organArray when prefixing it with "NSMutableArray" so if I understand your code, change your app delegate to:
organArray = [[NSMutableArray alloc] init];
instead of:
NSMutableArray *organArray = [[NSMutableArray alloc] init];

iPhone SDK NSDictionary and NSArray confusion

I have been trying to get this to work for about three solid days and get my mind around it. Can someone advise.
I have built the basics and they all work great but when I try to do that extra bit I cannot get my head around it.
I am trying to build a table of technical terms, from a plist. This is an indexed and sections table by the alphabet.
This works fine but when I then try to add the next level for each term's definition in a new viewcontroller I can't seem to get the code or the plist structure right.
At the moment I have created two plists. One with a dictionary of the alphabet in 26 arrays, within each array is a series of technical terms. All this works great.
Then I've created another plist of definitions as an array of dictionaries, one for each word/definition pair. I'm expecting to be passing the #"word" key from the view controller to the detailviewcontroller then picking up the #"definition". I don't know whether this is right or wrong(?)
My code shows the technical term table great but when a row is selected it crashes. I know it's to do with the code for passing the detailviewcontroller's reference so the detailview can pick up the definition - but I've no idea how to solve it. I've posted parts of my code here for someone to look at help. Any ideas?
NSString *wordPath = [[NSBundle mainBundle] pathForResource:#"newsortedglossary" ofType:#"plist"];
NSDictionary *wordDict = [[NSDictionary alloc] initWithContentsOfFile:wordPath];
self.words = wordDict;
[words release];
NSArray *wordArray = [[words allKeys] sortedArrayUsingSelector:#selector(compare:)];
self.wordKeys = wordArray;
NSString *definitionPath = [[NSBundle mainBundle] pathForResource:#"newnewdefinitionglossary" ofType:#"plist"];
NSDictionary *definitionDict = [[NSDictionary alloc] initWithContentsOfFile:definitionPath];
self.definitions = definitionDict;
[definitions release];
didSelectRow here.........
GlossaryDetailViewController *glossaryDetailViewController = [[GlossaryDetailViewController alloc]
initWithNibName:#"GlossaryDetailView" bundle:nil];
NSLog(#"did select-2"); // CRASHES HERE with NSDictionary may not respond to objectAtIndex
glossaryDetailViewController.definition = [self.words objectAtIndex:indexPath.row];
NSLog(#"did select-3");
[self.navigationController pushViewController:glossaryDetailViewController animated:YES];
NSLog(#"did select-4");
[glossaryDetailViewController release];
detailViewController here.......
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"didappear");
self.glossaryWordDefinition.text = [definition objectForKey:#"definition"];
It seems that you are trying to access the members of dictionary by using an index, instead of using a key to lookup the associated value.
In your didSelectRow you probably want this:
glossaryDetailViewController.definition = [self.wordKeys objectAtIndex:indexPath.row];
The difference is that now you are trying access the members of an array with the index.