How do I get TTTableViewDataSource to work with AddressBook - iphone

I would like to get a TTPickerTextField to search and get data from the build in AddressBook, and I understand I should make my own data source class that implements the TTTableViewDataSource protocol. But how do I implement it so that it connects correctly with the build in AddressBook? Im a newbie, so combining the Address Book Programming Guide for iOS and the API for TTTableViewDataSource is very confusing to me, so please help with some hints or even example(s).
Thank you

Here is an ABDataSource, that does exactly this. I'm using this in one of my apps. It will not work out of the box, because it depends on my 'DSMEmailAddress' class, but I hope it will point you in the right direction.
You may use this code under the terms of the zlib licence.
#interface ABDataSource : TTListDataSource {
ABAddressBookRef _addressBookRef;
NSMutableArray* _allItems;
NSMutableArray* _delegates;
}
+ (ABDataSource*)abDataSource:(BOOL)forSearch;
#end
#implementation ABDataSource
+ (ABDataSource*)abDataSource:(BOOL)forSearch {
ABDataSource* dataSource = [[[ABDataSource alloc] init] autorelease];
return dataSource;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)dealloc {
[_allItems release];
[super dealloc];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// UITableViewDataSource
- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView {
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// TTTableViewDataSource
- (NSString*)tableView:(UITableView*)tableView labelForObject:(id)object {
DSMEmailAdress* field = object;
return field.name;
}
- (Class)tableView:(UITableView*)tableView cellClassForObject:(id)object {
return [DSMEmailAddressTableCell class];
}
- (void)tableView:(UITableView*)tableView prepareCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath {
cell.accessoryType = UITableViewCellAccessoryNone;
((TTTableViewCell*)cell).object =[_items objectAtIndex:indexPath.row];
}
- (void)search:(NSString*)text {
if (nil == _allItems) {
_addressBookRef = ABAddressBookCreate ();
NSArray* allPeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(_addressBookRef);
_allItems = [[NSMutableArray alloc] initWithCapacity:[allPeople count]]; // capacity is only a rough guess, but better than nothing
for (id record in allPeople) {
CFTypeRef emailProperty = ABRecordCopyValue((ABRecordRef)record, kABPersonEmailProperty);
NSArray *emails = (NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
CFRelease(emailProperty);
for (NSString *email in emails) {
NSString* compositeName = (NSString *)ABRecordCopyCompositeName((ABRecordRef)record);
DSMEmailAdress* field = [[[DSMEmailAdress alloc] initWithName:compositeName mail:email] autorelease];
[compositeName release];
[_allItems addObject:field];
}
[emails release];
}
CFRelease(_addressBookRef);
_addressBookRef = nil;
[allPeople release];
allPeople = nil;
}
[_items release];
if (text.length) {
_items = [[NSMutableArray alloc] init];
for (DSMEmailAdress* mail in _allItems) {
if ([mail hasPrefix:text]) {
[_items addObject:mail];
}
}
if ([_items count]==0){
[_items release];
_items = nil;
}
} else {
_items = nil;
}
[_delegates perform:#selector(modelDidFinishLoad:) withObject:self];
}
#pragma mark TTModel
- (NSMutableArray*)delegates {
if (!_delegates) {
_delegates = TTCreateNonRetainingArray();
}
return _delegates;
}
- (BOOL)isLoadingMore {
return NO;
}
- (BOOL)isOutdated {
return NO;
}
- (BOOL)isLoaded {
return !!_allItems;
}
- (BOOL)isLoading {
return NO;
}
- (BOOL)isEmpty {
return !_items.count;
}
- (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {
}
- (void)invalidate:(BOOL)erase {
}
- (void)cancel {
[_delegates perform:#selector(modelDidCancelLoad:) withObject:self];
}
#end

Related

Selecting events using Kal calendar

I'm adding a calendar view to my app using Kal Calendar but am having problems implementing a didSelectRowAtIndexPath method on the event list. I would like to push a view controller when the user selects an event for any given day. I've tried putting the method in "KalView.m", "KalViewController.m", and "KalDataSource.m", but none are recognized. Where is the appropriate place to call such a method?
I had similar issue once, Here is how I implemented it.
#import <MTDates/NSDate+MTDates.h>
#import <ObjectiveSugar/ObjectiveSugar.h>
#import <UIImageView+WebCache.h>
#import "EventsViewController.h"
#import "EventDetailsViewController.h"
#import "EventCell.h"
#import "Event.h"
#import "KalViewController.h"
#import "CalendarViewController.h"
#implementation EventsViewController
- (id)initWithEvents:(NSArray *)_events {
self = [super init];
events = _events;
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self listUpdated];
[self addCalendarView];
}
- (void)listUpdated
{
NSMutableArray *allEvents = [NSMutableArray array];
[allEvents addObjectsFromArray:events];
NSArray *sortedArray = [allEvents sortedArrayUsingComparator:^NSComparisonResult(Event *obj1, Event *obj2) {
return [obj1.date compare:obj2.date];
}];
_allEvents = sortedArray;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_allEvents count];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//custom table cell (EventCell is a view I'm initialising my rows with)
Event *event = _allEvents[indexPath.row];
NSString *reuseIdentifier = [NSString stringWithFormat:#"Cell%#%#", event.venue.identifier, event.identifier];
EventCell *cell = (EventCell*) [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (!cell) {
cell = [EventCell createDetailedCellWithReuseIdentifier:reuseIdentifier];
cell.nameLabel.text = event.name;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Event *event = _allEvents[indexPath.row];
EventDetailsViewController *controller = [[EventDetailsViewController alloc] initWithEvent:event];
[self.navigationController pushViewController:controller animated:YES];
}
- (void) addCalendarView{
_calenderView = [[KalViewController alloc] initWithSelectedDate:[NSDate date]];
[[self.view viewWithTag:2] addSubview:_calenderView.view]; /* depends on your requirements*/
_calenderView.view.tag = 200; /* not necessary */
[_calenderView.view setFrame:self.view.bounds];
_calenderView.dataSource = self;
_calenderView.delegate = self;
}
- (void)loadItemsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
//NSLog(#"%#, %#", fromDate, toDate);
// filter and pass the array to the events tableview
[self filterByDateSelected:toDate];
}
-(void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
/** when selecting a different month **/
}
- (void)removeAllItems
{
NSLog(#"Items Removed");
// remove all the previous items from the tableview
}
-(void) filterByDateSelected: (NSDate *)selectedDate
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];
NSString *theDate = [dateFormat stringFromDate:selectedDate];
NSDate *_date = [NSDate dateFromString:theDate usingFormat:#"yyyy-MM-dd"];
// filter table by selectedDate
NSArray *_dateFilteredEvents = _allEvents;
_dateFilteredEvents = [_allEvents filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Event *evaluatedEvent, NSDictionary *bindings) {
if ([evaluatedEvent.date isEqualToDate:_date]) {
return YES;
}
return NO;
}]];
NSLog(#"%#", _dateFilteredEvents);
// uncomment the following line if you want to display list in another controller
//[self showEventsByDate:_dateFilteredEvents];
// or else refresh table after updating the list
_allEvents = _dateFilteredEvents;
[_tableView reloadData];
}
- (void) showEventsByDate:(NSArray*)events
{
if (events.count > 0) {
CalendarViewController *_controller = [[CalendarViewController alloc] initWithEventArray:events];
[self.navigationController pushViewController:_controller animated:YES];
}
}
- (void) removeCalenderView{
[_calenderView.view removeFromSuperview];
}
#end

Sending a email message using app in mailcore xcode:error in text of body of the mail missing

This is the implementation file.Mail is sending but the problem is text in the body of mail is missing to the recepient of mail,can any one pls help me...... how to rectify the this issue
#implementation MyController
- (id)init
{
self = [super init];
if(self)
{
myMessage = [[CTCoreMessage alloc] init];
}
return self;
}
- (void)dealloc
{
[myMessage release];
[super dealloc];
}
- (IBAction)sendMessage:(id)sender
{
CTCoreMessage *msg = [[CTCoreMessage alloc] init];
[msg setTo:[myMessage to]];
[msg setFrom:[myMessage from]];
[msg setBody:[myMessage body]];
[msg setSubject:[myMessage subject]];
BOOL auth = ([useAuth state] == NSOnState);
BOOL tls = ([useTLS state] == NSOnState);
[CTSMTPConnection sendMessage:msg server:[server stringValue] username:[username stringValue]
password:[password stringValue] port:[port intValue] useTLS:tls useAuth:auth];
[msg release];
}
- (NSString *)to
{
return [[[myMessage to] anyObject] email];
}
- (void)setTo:(NSString *)aValue
{
CTCoreAddress *addr = [CTCoreAddress address];
[addr setEmail:aValue];
[myMessage setTo:[NSSet setWithObject:addr]];
}
- (NSString *)from
{
return [[[myMessage from] anyObject] email];
}
- (void)setFrom:(NSString *)aValue
{
CTCoreAddress *addr = [CTCoreAddress address];
[addr setEmail:aValue];
[addr setName:#""];
[myMessage setFrom:[NSSet setWithObject:addr]];
}
- (NSString *)subject
{
return [myMessage subject];
}
- (void)setSubject:(NSString *)aValue
{
[myMessage setSubject:aValue];
}
- (NSString *)body
{
return [myMessage body];
}
- (void)setBody:(NSString *)aValue
{
[myMessage setBody:aValue];
}
#end
You have cyclical references in there, Rehana.
Look at your setBody method.
You're trying to set the body of myMessage to the current body of myMessage. Both of which are NULL.
You need to set the values in myMessage object first there is no need to calling the same thing again.
Here how you will do this
- (IBAction)sendMessage:(id)sender
{
//Assuming textfields with the names I have passed as parameter.
//This is only for demonstration
//Set body to myMessage object from textview
[self setBody:bodytextview.text];
[self setTo:txtfTo.text];
[self setFrom:txtfFrom.text];
[self setSubject:txtfSubject.text];
BOOL auth = ([useAuth state] == NSOnState);
BOOL tls = ([useTLS state] == NSOnState);
//Note I'm passing myMessage Object
[CTSMTPConnection sendMessage:myMessage server:[server stringValue] username:[username stringValue]
password:[password stringValue] port:[port intValue] useTLS:tls useAuth:auth];
}

Imlementation of Singleton Class

i have been using mostly the appDelegate class for global variables but recently i came to know that its not a gud way for keeping global variables so i am trying to make a singleton class as following
#implementation globalVar
static globalVar *_sharedInstance =nil;
#synthesize totalTime;
- (id) init
{
if (self = [super init])
{
}
return self;
}
+ (globalVar *) sharedInstance
{
#synchronized (self) {
if (_sharedInstance == nil) {
[[self alloc] init];
}
}
return _sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if (_sharedInstance == nil) {
_sharedInstance = [super allocWithZone:zone];
return _sharedInstance;
}
}
return nil;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
-(NSUInteger)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release
{
// do nothing
}
- (id)autorelease
{
return self;
}
- (void) setTotalTime:(NSString *)time
{
#synchronized(self) {
if (totalTime != time) {
[totalTime release];
totalTime = [NSString stringWithFormat:#"%#",time];
}
}
//NSLog(#"time %#",totalTime);
}
-(NSString *)getTotalTime
{
#synchronized(self) {
//NSLog(#"total %#",totalTime);
return totalTime;
}
}
when i set the value for totaltime in my appDelegate class and retrieve it in that class only i get the correct value. but when i only retrieve the value in some other class i get BAD EXCESS. i first create the sharedinstance and then only call this method then why am i getting this error??
globalVar *myEngine = [globalVar sharedInstance];
NSLog(#"about %#",[myEngine totalTime]);
in my app delegate
globalVar *myEngine = [globalVar sharedInstance];
[myEngine setTotalTime:totalTime];
NSLog(#"in app delegate%#",[myEngine getTotalTime]);
You're releasing totalTime but not retaining the new value, which means that when you access it it's already been released, causing a bad access exception.
You can correct this by changing the line where you set the value to include a call to retain:
totalTime = [[NSString stringWithFormat:#"%#",time] retain];
Have a look at the discussion here:
Is it good practice to use AppDelegate for data manipulation and Handling?

iPhone sdk: how to solve this warnings

hi i am working with Twitter, in this there will be two class, for showing tweet in table
view and retrieving string for table view like user photos, screen name, username and date
one class is MyTweetViewController.h //I am importing the Tweet class also
and next one is Tweet.h class
//this line i am getting warning i.e NO initWithTweetDictionary method not found,
Tweet *tweet =[[Tweet alloc] initWithTweetDictionary:tweetDict];
- -(void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier
// this is delegate for MGTwitter for retrieving information of user
{
NSLog(#"Statuses Receives: %#",statuses);
{
tweetArray = [[NSMutableArray alloc] init];
for(NSDictionary *tweetDict in statuses)
{
Tweet *tweet =[[Tweet alloc] initWithTweetDictionary:tweetDict];// here i am getting
warring i.e NO initWithTweetDictionary method not found,
[tweetArray addObject:tweet];
[tweet release];
}
}
[self.tweetsTableView reloadData];
}
////Tweet.h
#import <UIKit/UIKit.h>
#interface Tweet : NSObject {
NSDictionary *contentsTweet;
}
-(NSString*)userName;
-(NSString*)tweet;
-(NSString*)image_url;
-(NSString*)created_at;
#end
///Tweet.m
#import "Tweet.h"
#implementation Tweet
-(id)initWithTweetDictionary:(NSDictionary*)_contentsTweet {
if(self = [super init]) {
contentsTweet = _contentsTweet;
[contentsTweet retain];
}
return self;
}
-(NSString*)userName {
NSDictionary * dic = (NSDictionary*)[contentsTweet objectForKey:#"user"];
return [dic objectForKey:#"name"];
}
-(NSString*)tweet {
return [contentsTweet objectForKey:#"text"];
}
-(NSString*)image_url {
NSDictionary * dic = (NSDictionary*)[contentsTweet objectForKey:#"user"];
return [dic objectForKey:#"profile_image_url"];
}
- (void)dealloc {
[contentsTweet release];
[super dealloc];
}
#end
Please suggest me
Thank you
in Tweet.h you have to declare -(id)initWithTweetDictionary:(NSDictionary*)_contentsTweet;
in order to make the warning dissappear.
#interface Tweet : NSObject {
NSDictionary *contentsTweet;
}
-(id)initWithTweetDictionary:(NSDictionary*)_contentsTweet;
-(NSString*)userName;
-(NSString*)tweet;
-(NSString*)image_url;
-(NSString*)created_at;
#end

Property changes but I can't figure out who's doing it

I have a UIViewController (called AdjustViewController) that presents another UIViewController (called SourcePickerViewController) with a UIPickerView modally. I generate instances of the AdjustViewController and they in turn make a SourcePickerViewController. I make an NSDictionary and assign it and an integer to the AdjustViewController and it in turn sets the same properties in the SourcePickerController. This way I can reuse the controllers. The NSDictionary get set up in a UITableViewController that has all the AdjustViewControllers in it.
The problem comes when some of the pickers should have 1 component and some should have 2. The integer that I pass along is called numberOfComponents When I make a picker with numberOfComponents = 1 somehow it's changing to = 2 but I can't see how. I have NSLogs all over the place and I can see it happen as soon as the picker delegate method numberOfComponentsInPickerView is called. It's 1 right before and 2 right after.
There's obviously more code, but I think I have all the important parts. Although if that were true, maybe I'd know where the problem is!
Inside MenuViewController.m
- (void)viewDidLoad {
NSLog(#"ChemicalViewController launched");
self.title = #"Adjust Chemicals";
NSMutableArray *array = [[NSMutableArray alloc] init];
// Chlorine Controller
AdjustViewController *chlorineAdjustViewController = [[AdjustViewController alloc] initWithNibName:#"AdjustViewController" bundle:nil];
chlorineAdjustViewController.title = #"FC - Free Chlorine";
chlorineAdjustViewController.numberOfComponents = 2;
NSLog(#"Generating chlorine source dictionary");
NSDictionary *chlorineSourceDictionary = [self generateChlorineDictionary];
chlorineAdjustViewController.dictionaryOfSources = chlorineSourceDictionary;
[chlorineSourceDictionary release];
[array addObject:chlorineAdjustViewController];
[chlorineAdjustViewController release];
// CYA Controller
AdjustViewController *cyaAdjustViewController = [[AdjustViewController alloc] initWithNibName:#"AdjustViewController" bundle:nil];
cyaAdjustViewController.title = #"CYA - Cyanuric Acid";
cyaAdjustViewController.numberOfComponents = 1;
NSLog(#"Generating cya source dictionary");
NSDictionary *cyaSourceDictionary = [self generateCYADictionary];
cyaAdjustViewController.dictionaryOfSources = cyaSourceDictionary;
[cyaSourceDictionary release];
[array addObject:cyaAdjustViewController];
[cyaAdjustViewController release];
Inside AdjustViewController.m
// Present the picker for chlorine selection
- (IBAction)getChemicalSource {
SourcePickerViewController *sourcePickerViewController = [[SourcePickerViewController alloc] init];
sourcePickerViewController.delegate = self;
NSLog(#"getChemicalSource setting numberOfComponents %d", self.numberOfComponents);
sourcePickerViewController.numberOfComponents = self.numberOfComponents;
NSLog(#"getChemicalSource sending numberOfComponents %d", sourcePickerViewController.numberOfComponents);
sourcePickerViewController.dictionaryOfSources = self.dictionaryOfSources;
[self presentModalViewController:sourcePickerViewController animated:YES];
[sourcePickerViewController release];
}
#pragma mark -
#pragma mark Picker View Delegate Methods
// Returns the values from the picker if a source was chosen
- (void)sourcePickerViewController:(SourcePickerViewController *)controller
didSelectSource:(NSString *)source
andConcentration:(NSString *)concentration
andConstant:(float)constant
andIsLiquid:(BOOL)isLiquid {
sourceField.text = [[NSString alloc] initWithFormat:#"%#, %#", source, concentration];
[self updateAdvice];
NSLog(#"Returned source = %#, concentration = %#, sourceConstant = %1.7f, isLiquid = %d", source, concentration, constant, isLiquid);
[self dismissModalViewControllerAnimated:YES];
}
// Returns from the picker without choosing a new source
- (void)sourcePickerViewController:(SourcePickerViewController *)controller
didSelectCancel:(BOOL)didCancel {
[self updateAdvice];
NSLog(#"Returned without selecting source");
[self dismissModalViewControllerAnimated:YES];
}
Inside SourceViewController.m
- (void)viewDidLoad {
NSLog(#"SourcePickerViewController launched");
NSLog(#"viewDidLoad");
NSLog(#"Received numberOfComponents %d", self.numberOfComponents);
self.chemicalSources = dictionaryOfSources;
NSArray *components = [self.chemicalSources allKeys];
NSArray *sorted = [components sortedArrayUsingSelector:#selector(compare:)];
self.sources = sorted; // This array has the chemical sources
if (self.numberOfComponents = 2) {
NSString *selectedSource = [self.sources objectAtIndex:0];
NSArray *chemArray = [self.chemicalSources objectForKey:selectedSource];
NSMutableArray *concentrationArray = [[NSMutableArray alloc] init];
int num = [chemArray count];
for (int i=0; i<num; i++) {
[concentrationArray addObject:[[chemArray objectAtIndex:i] chemConcentration]];
}
self.concentrations = concentrationArray;
}
[super viewDidLoad];
}
#pragma mark -
#pragma mark Picker Data Source Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
NSLog(#"numberOfComponentsInPickerView, self.numberOfComponents = %d", self.numberOfComponents);
return self.numberOfComponents;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSLog(#"numberOfRowsInComponent, self.numberOfComponents = %d", self.numberOfComponents);
if (component == kSourceComponent)
return [self.sources count];
return [self.concentrations count];
}
#pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if (component == kSourceComponent)
return [self.sources objectAtIndex:row];
return [self.concentrations objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSLog(#"didSelectRow, self.numberOfComponents = %d", self.numberOfComponents);
if (numberOfComponents = 2) {
if (component == kSourceComponent) {
NSString *selectedSource = [self.sources objectAtIndex:row];
NSArray *chemArray = [self.chemicalSources objectForKey:selectedSource];
NSMutableArray *concentrationArray = [[NSMutableArray alloc] init];
int num = [chemArray count];
for (int i=0; i<num; i++) {
[concentrationArray addObject:[[chemArray objectAtIndex:i] chemConcentration]];
}
self.concentrations = concentrationArray;
[picker selectRow:0 inComponent:kConcentrationComponent animated:YES];
[picker reloadComponent:kConcentrationComponent];
}
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
if (component == kConcentrationComponent)
return 90;
return 205;
}
I didn't look through all of your code; Instead, I'd recommend writing out the properties for numberOfComponents instead of #synthesize'ing them. Just get rid of your #synthesize, and make:
- (int)numberOfComponents {
return m_numberOfComponents;
}
and
- (void)setNumberOfComponents(int aNumberOfComponents) {
m_numberOfComponents = aNumberOfComponents;
}
Then, set a breakpoint in your setNumberOfComponents function, and you should be able to see whenever it's getting called, so you can see what is going on. I hope that helps!