iPhone sdk: how to solve this warnings - iphone

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

Related

help with singleton's

I am trying to create a singleton User class in my app, here's the code:
#import "User.h"
#import "Login.h"
#import "SFHFKeychainUtils.h"
// Constants
static NSString* const kDBUserCurrentUserIDDefaultsKey = #"kDBUserCurrentUserIDDefaultsKey";
// Current User singleton
static User* currentUser = nil;
#implementation User
#synthesize username = _username;
#synthesize password = _password;
#synthesize delegate = _delegate;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
+ (NSString*)primaryKeyProperty {
return #"username";
}
+ (User*)currentUser {
if (nil == currentUser) {
id username = [[NSUserDefaults standardUserDefaults] objectForKey:#"kApplicationUserNameKey"];
if (!username) {
currentUser = [self new];
} else{
NSLog(#"CURRENT USER");
return self;
}
[currentUser retain];
}
return currentUser;
}
+ (void)setCurrentUser:(User*)user {
[user retain];
[currentUser release];
currentUser = user;
}
/**
* Implementation of a RESTful login pattern. We construct an object loader addressed to
* the /login resource path and POST the credentials. The target of the object loader is
* set so that the login response gets mapped back into this object, populating the
* properties according to the mappings declared in elementToPropertyMappings.
*/
- (void)loginWithUsername:(NSString*)username andPassword:(NSString*)password delegate:(NSObject<DBUserAuthenticationDelegate>*)delegate {
_delegate = delegate;
//[RKObjectManager sharedManager].client.username = username;
//[RKObjectManager sharedManager].client.password = password;
self.username = username;
self.password = password;
RKObjectMapping * userMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:#"LoginViewController"];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/account/verify.json" objectMapping:userMapping delegate:self];
}
/**
* Implementation of a RESTful logout pattern. We POST an object loader to
* the /logout resource path. This destroys the remote session
*/
- (void)logout/*:(NSObject<DBUserAuthenticationDelegate>*)delegate */{
NSError * error = nil;
[[NSUserDefaults standardUserDefaults] setValue:nil forKey:#"kApplicationUserNameKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
[SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:#"convore" error:&error];
NSLog(#"LOGGING OUT");
if ([self.delegate respondsToSelector:#selector(userDidLogout:)]) {
[self.delegate userDidLogout:self];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"DBUserDidLogoutNotification" object:nil];
}
- (void)loginWasSuccessful {
// Upon login, we become the current user
[User setCurrentUser:self];
NSError * error = nil;
// Persist the username for recovery later
[[NSUserDefaults standardUserDefaults] setValue:self.username forKey:#"kApplicationUserNameKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
[SFHFKeychainUtils storeUsername:self.username andPassword:self.password forServiceName:#"convore" updateExisting:TRUE error:&error];
// Inform the delegate
if ([self.delegate respondsToSelector:#selector(userDidLogin:)]) {
[self.delegate userDidLogin:self];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"DBUserDidLoginNotification" object:self];
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
NSLog(#"Loaded payload: %#", [response bodyAsString]);
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObject:(id)object
{
if ([objectLoader wasSentToResourcePath:#"/account/verify.json"]) {
Login * login = (Login *) object;
if ([login.username length] > 0)
[self loginWasSuccessful];
}
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError*)error {
if ([objectLoader wasSentToResourcePath:#"/account/verify.json"]) {
NSLog(#"Encountered an error: %#", error);
// Login failed
if ([self.delegate respondsToSelector:#selector(user:didFailLoginWithError:)]) {
[self.delegate user:self didFailLoginWithError:error];
}
}
}
- (BOOL)isLoggedIn {
return self.username != nil;
//return self.singleAccessToken != nil;
}
- (void)dealloc {
_delegate = nil;
[_password release];
[_passwordConfirmation release];
[super dealloc];
}
#end
The issue is that whenever I tried to access currentUser it always breaks down. I first called the loginWithUsernameandPassword and then tried calling the currentUser, but when I call the currentUser on logout, it gives me an error:
calling this:
if ([[User currentUser] isLoggedIn])
gives me:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[User isLoggedIn]: unrecognized selector sent to class 0x1a671c'
seems that currentUser is nil, why is this?
Quick Singleton 101 (I wish I had this when I started, lol. Everyone just pointed me to the docs which didn't help much). The name of the singleton is going to be "Singleton"
//Singleton.h
#import <Foundation/Foundation.h>
#interface SingletonManager : NSObject
{
NSDictionary* randomDictionary; //just using a dictionary for demonstrative purposes. You can make this a string or whatever you want.
}
+ (Singleton*)sharedSingleton;
#property (nonatomic, retain) NSDictionary *randomDictionary;
#end
And now the .m
//Singleton.m
#import "Singleton.h"
static Singleton *sharedSingleton = nil;
#implementation Singleton
#synthesize randomDictionary;
#pragma mark Singleton Method
+ (Singleton*)sharedSingleton
{
#synchronized(self)
{
if(sharedSingleton == nil)
{
sharedSingleton = [[super allocWithZone:NULL] init];
}
}
return sharedSingleton;
}
#end
And to set/get, first import the singleton in whatever class you need: #import "Singleton.h", then grab the singleton with Singleton *singletonManager = [Singleton sharedSingleton]; and then you can do whatever you need to as necessary. i.e. to get the description of the NSDictionary you would call [[singletonManager randomDictionary] description];
Now this is using ARC, so if you are not you'd just have to make sure you manage your memory correctly. Enjoy.
You need to get the singleton object before you can call a method on it.
if ( [[User currentUser] isLoggedIn] ) {
// Magic happens here
}
You aren't coding your singleton properly.
+ (User *) currentUser {
#synchronized (self) {
if (currentUser == nil) {
currentUser = [[self alloc] init];
}
return currentUser;
}
}
The answer is really a combo of the two answers from XCodeDev and Matthieu Cormier. You need to "protect" your init the way the code sample says so new versions of the object are not created. Otherwise, its not a real singleton. More info on Singleton pattern.
Also, just because its a singleton doesn't mean you can access it with just class methods after you initialize it. You still need to get the instance you initialized, otherwise you cannot do operations that require certain values only in the instance.

How do I get TTTableViewDataSource to work with AddressBook

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

Sorting global data alphbetically

I am storing the parsed xml values as Global data in Mutable Array some thing like this...
.h file
#interface GlobalData : NSObject {
NSMutableArray *array;
}
#property(nonatomic,retain) NSMutableArray *array;
(id)sharedData;
In .m file
static GlobalData *sharedGlobalData = nil;
#implementation GlobalData
#synthesize array;
+(id)sharedData{
#synchronized(self) {
if(sharedGlobalData == nil)
{
sharedGlobalData=[[GlobalData alloc] init];
sharedGlobalData.boats=[[NSMutableArray alloc] init];
}
}
return sharedGlobalData;
}
(id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if(sharedGlobalData == nil) {
sharedGlobalData = [super allocWithZone:zone];
return sharedGlobalData;
}
}
return nil;
}
I am passing the value of array to a Table view and displaying it as a table. Now i want to sort this array alphbetically from A-Z and pass it to table view.How can i do this???... Plz help
Got it by using NSSortDescriptor....
something like this,
NSSortDescriptor *alphaDesc = [[NSSortDescriptor alloc] initWithKey:#"boatName" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
[[data boats] sortUsingDescriptors:[NSMutableArray arrayWithObjects:alphaDesc, nil]];

Singleton Class iPhone

Ok, I'm trying to avoid global variables, so I read up on singleton classes.
This is a try to set and read a mutable array, but the result is null.
//Content.h
#interface Content : NSObject {
NSMutableArray *contentArray;
}
+ (Content *) sharedInstance;
- (NSMutableArray *) getArray;
- (void) addArray:(NSMutableArray *)mutableArray;
#end
.
//Content.m
#implementation Content
static Content *_sharedInstance;
+ (Content *) sharedInstance
{
if (!_sharedInstance)
{
_sharedInstance = [[Content alloc] init];
}
return _sharedInstance;
}
- (NSMutableArray *) getArray{
return contentArray;
}
- (void) addArray:(NSMutableArray *)mutableArray{
[contentArray addObject:mutableArray];
}
#end
And in a ViewController I added #import "Content.h", where I try to call this:
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:#"test",#"foo",#"bar",nil];
Content *content = [Content sharedInstance];
[content addArray:mArray];
NSLog(#"contentArray: %#", [content getArray]);
You need to alloc and init the array first. Personally I'd do it in the init method of the content class like so:
-(id)init{
if(self = [super init]){
…the rest of your init code…
contentArray = [[NSMutableArray alloc] init];
}
return self;
}
You never actually alloc/initialise the contentArray array.

Instantiating Custom Class from NSDictionary

I have a feeling that this is stupid question, but I'll ask anyway...
I have a collection of NSDictionary objects whose key/value pairs correspond to a custom class I've created, call it MyClass. Is there an easy or "best practice" method for me to basically do something like MyClass * instance = [map NSDictionary properties to MyClass ];? I have a feeling I need to do something with NSCoding or NSKeyedUnarchiver, but rather than stumble through it on my own, I figure someone out there might be able to point me in the right direction.
The -setValuesForKeysWithDictionary: method, along with -dictionaryWithValuesForKeys:, is what you want to use.
Example:
// In your custom class
+ (id)customClassWithProperties:(NSDictionary *)properties {
return [[[self alloc] initWithProperties:properties] autorelease];
}
- (id)initWithProperties:(NSDictionary *)properties {
if (self = [self init]) {
[self setValuesForKeysWithDictionary:properties];
}
return self;
}
// ...and to easily derive the dictionary
NSDictionary *properties = [anObject dictionaryWithValuesForKeys:[anObject allKeys]];
There is no allKeys on NSObject. You'll need to create an extra category on NSObject like below:
NSObject+PropertyArray.h
#interface NSObject (PropertyArray)
- (NSArray *) allKeys;
#end
NSObject+PropertyArray.m
#import <objc/runtime.h>
#implementation NSObject (PropertyArray)
- (NSArray *) allKeys {
Class clazz = [self class];
u_int count;
objc_property_t* properties = class_copyPropertyList(clazz, &count);
NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++) {
const char* propertyName = property_getName(properties[i]);
[propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
}
free(properties);
return [NSArray arrayWithArray:propertyArray];
}
#end
Example:
#import "NSObject+PropertyArray.h"
...
MyObject *obj = [[MyObject alloc] init];
obj.a = #"Hello A"; //setting some values to attributes
obj.b = #"Hello B";
//dictionaryWithValuesForKeys requires keys in NSArray. You can now
//construct such NSArray using `allKeys` from NSObject(PropertyArray) category
NSDictionary *objDict = [obj dictionaryWithValuesForKeys:[obj allKeys]];
//Resurrect MyObject from NSDictionary using setValuesForKeysWithDictionary
MyObject *objResur = [[MyObject alloc] init];
[objResur setValuesForKeysWithDictionary:objDict];
Assuming that your class conforms to the Key-Value Coding protocol, you could use the following: (defined as a category on NSDictionary for convenience):
// myNSDictionaryCategory.h:
#interface NSDictionary (myCategory)
- (void)mapPropertiesToObject:(id)instance
#end
// myNSDictionaryCategory.m:
- (void)mapPropertiesToObject:(id)instance
{
for (NSString * propertyKey in [self allKeys])
{
[instance setValue:[self objectForKey:propertyKey]
forKey:propertyKey];
}
}
And here's how you would use it:
#import "myNSDictionaryCategory.h"
//...
[someDictionary mapPropertiesToObject:someObject];
If your doing this sort of thing chances are your dealing with JSON and you should probably have a look at Mantle
https://github.com/Mantle/Mantle
You will then get a convenient method dictionaryValue
[anObject dictionaryValue];
Just add category for NSObject for getting dictionaryRepresentation from your custom objects (in my case using in JSON serialization only):
// NSObject+JSONSerialize.h
#import <Foundation/Foundation.h>
#interface NSObject(JSONSerialize)
- (NSDictionary *)dictionaryRepresentation;
#end
// NSObject+JSONSerialize.m
#import "NSObject+JSONSerialize.h"
#import <objc/runtime.h>
#implementation NSObject(JSONSerialize)
+ (instancetype)instanceWithDictionary:(NSDictionary *)aDictionary {
return [[self alloc] initWithDictionary:aDictionary];
}
- (instancetype)initWithDictionary:(NSDictionary *)aDictionary {
aDictionary = [aDictionary clean];
self.isReady = NO;
for (NSString* propName in [self allPropertyNames]) {
[self setValue:aDictionary[propName] forKey:propName];
}
//You can add there some custom properties with wrong names like "id"
//[self setValue:aDictionary[#"id"] forKeyPath:#"objectID"];
self.isReady = YES;
return self;
}
- (NSDictionary *)dictionaryRepresentation {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
NSArray *propertyNames = [self allPropertyNames];
id object;
for (NSString *key in propertyNames) {
object = [self valueForKey:key];
if (object) {
[result setObject:object forKey:key];
}
}
return result;
}
- (NSArray *)allPropertyNames {
unsigned count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableArray *rv = [NSMutableArray array];
unsigned i;
for (i = 0; i < count; i++) {
objc_property_t property = properties[i];
NSString *name = [NSString stringWithUTF8String:property_getName(property)];
[rv addObject:name];
}
//You can add there some custom properties with wrong names like "id"
//[rv addObject:#"objectID"];
//Example use inside initWithDictionary:
//[self setValue:aDictionary[#"id"] forKeyPath:#"objectID"];
free(properties);
return rv;
}
#end
Also, you can see that my solution will not work with custom objects with nested objects or arrays. For Arrays - just change the lines of code in dictionaryRepresentation method:
if (object) {
if ([object isKindOfClass:[NSArray class]]) {
#autoreleasepool {
NSMutableArray *array = [NSMutableArray array];
for (id item in (NSArray *)object) {
[array addObject:[item dictionaryRepresentation]];
}
[result setObject:array forKey:key];
}
} else {
[result setObject:object forKey:key];
}
}