RestKit Reachability null - iphone

I have the following code in my AppDelegate.m - the result of the NSLog is always (null) and thus the condition for no reachability is never fired. I would like to know why this is happening/what I am doing incorrectly.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[IKRestKitManager configureRestKit];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[self prepareForLogin];
return YES;
}
#pragma mark - onstart
- (void)prepareForLogin {
if ([[[RKClient sharedClient] reachabilityObserver] isReachabilityDetermined] && ![[RKClient sharedClient] isNetworkReachable]) {
UIAlertView *reachAV = [[UIAlertView alloc] initWithTitle:#"Cannot connect to Internet" message:#"iK9 cannot reach the Internet. Please be sure that your device is connected to the Internet and try again." delegate:self cancelButtonTitle:#"Retry" otherButtonTitles:nil];
reachAV.tag = 0;
[reachAV show];
}
NSLog(#"%#",[[[RKClient sharedClient] reachabilityObserver] isReachabilityDetermined]);
if (![IKUserController loggedInUser]) {
IKLoginViewController *loginVC = [[IKLoginViewController alloc] init];
loginVC.scenario = SCENARIO_NEW;
[self.window.rootViewController presentModalViewController:loginVC animated:YES];
}
}

According to th documentation for RKReachabilityObserver:
When initialized, RKReachabilityObserver instances are in an indeterminate state to indicate that reachability status has not been yet established. After the first callback is processed by the observer, the observer will answer YES for reachabilityDetermined and networkStatus will return a determinate response.
You need to wait until the reachability status has been determined before checking if a connection is available. This is why your first if statement is not triggering.
To monitor this change, setup a notification observer (from this Stack Overflow question):
[[NSNotificationCenter defaultCenter] addObserver:self
                                      selector:#selector(reachabilityStatusChanged:)
                                      name:RKReachabilityDidChangeNotification object:nil];

BOOLean values are not objects, so %# is not their string literal. They are actually unsigned char, but you NSLog them with:
NSLog([[[RKClient sharedClient] reachabilityObserver] isReachabilityDetermined] ? #"Yes" : #"No");

Here is some changes in RestKit 0.20 and later. The code of reachability block should looks like:
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[RemoteTools serverUrl]];
[manager.HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
if (status == AFNetworkReachabilityStatusNotReachable) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No network connection"
message:#"You must be connected to the internet to use this app."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}]

Related

want to know the state of the Notification center whether is in "ON" or "OFF" state in ios5 and ios6

I want to know the state of the Notification center whether is in "ON" or "OFF" state.
As I know every one says to enable that by using
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
BUt i need to get the state either "ON" or "OFF" state.
I searched google results are:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
{
}
and
if (launchOptions != nil)
   {
       NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
       if (dictionary != nil)
       {
           NSLog(#"Launched from push notification: %#", dictionary);
           [self clearNotifications];
       }
   }
and
if (notificationTypes == UIRemoteNotificationTypeNone) {
// Do what ever you need to here when notifications are disabled
} else if (notificationTypes == UIRemoteNotificationTypeBadge) {
// Badge only
} else if (notificationTypes == UIRemoteNotificationTypeAlert) {
// Alert only
} else if (notificationTypes == UIRemoteNotificationTypeSound) {
// Sound only
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)) {
// Badge & Alert
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)) {
// Badge & Sound
} else if (notificationTypes == (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)) {
// Alert & Sound
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)) {
// Badge, Alert & Sound
}
But i did not get result both ios5 and ios6
Please Guide me
Thanks in Advance
There is a combination of 2 things you can do to make sure you always know when the user does not have notifications enabled in a specific way.
You must handle both didRegisterForRemoteNotificationsWithDeviceToken and didFailToRegisterForRemoteNotificationsWithError in your AppDelegate.
Example
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if (!([[UIApplication sharedApplication] enabledRemoteNotificationTypes] & UIRemoteNotificationTypeAlert) || !([[UIApplication sharedApplication] enabledRemoteNotificationTypes] & UIRemoteNotificationTypeBadge)) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Notice" message:#"You do not have the recommended notification settings enabled for this app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Notice" message:#"Your device does not currently have notifications enabled." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
FYI: This will always trigger in the simulator so you may want to comment it out until you test on a device as it becomes annoying.

Update plist from background

Is it possible to read or write to plist when the application is in background state?
It is not possible to read your plist when your application is in the background, because your application is not running more than 10 minutes in the background state. There are only three options for keeping your application running more than 10 minutes in the background.
If you want to read and write your plist, do this when your application comes to the foreground state. For this you can read and write your plist in the application became active delegate method.
try this one..
- (void)readPlist
{
    NSString *filePath = #"/System/Library/CoreServices/SystemVersion.plist";
        NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
       
        NSString *value;
        value = [plistDict objectForKey:#"ProductVersion"];
     
        /* You could now call the string "value" from somewhere to return the value of the string in the .plist specified, for the specified key. */
}
- (void)writeToPlist
{
    NSString *filePath = #"/System/Library/CoreServices/SystemVersion.plist";
        NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
       
        [plistDict setValue:#"1.1.1" forKey:#"ProductVersion"];
        [plistDict writeToFile:filePath atomically: YES];
/* This would change the firmware version in the plist to 1.1.1 by initing the NSDictionary with the plist, then changing the value of the string in the key "ProductVersion" to what you specified */
}
Hope this helps you!

How to partition this into a method

I am trying to refactor my code so that it follows good OO pattern, which is reusability and less repetition.. I have the following code:
PFQuery * query = [PFQuery queryWithClassName:#"Vote"];
query.cachePolicy = kPFCachePolicyNetworkElseCache;
[query whereKey:#"poll" equalTo:self.vote];
[query whereKey:#"note" notEqualTo:nil];
[query countObjectsInBackgroundWithBlock:^(int number, NSError * error) {
note = number;
[self.noteCount addSubview:self.generateCountLabel];
if (note > 0){
[self.note setUserInteractionEnabled:YES];
[self.note setEnabled:YES];
}
}];
PFQuery * query1 = [PFQuery queryWithClassName:#"Vote"];
query1.cachePolicy = kPFCachePolicyNetworkElseCache;
[query1 whereKey:#"poll" equalTo:self.vote];
[query1 whereKey:#"image" notEqualTo:nil];
[query countObjectsInBackgroundWithBlock:^(int number, NSError * error) {
pic = number;
[self.picCount addSubview:self.generateCountLabel];
if (pic > 0){
[self.pic setUserInteractionEnabled:YES];
[self.pic setEnabled:YES];
}
}];
Found it really difficult to partition into one method without doing a lot of if's. Any idea?
You can have the following method....
- (void)queryForKey:(NSString *)aKey view:(UIView *)aView countView:(UIView *)aCountView {
PFQuery * query = [PFQuery queryWithClassName:#"Vote"];
query.cachePolicy = kPFCachePolicyNetworkElseCache;
[query whereKey:#"poll" equalTo:self.vote];
[query whereKey:aKey notEqualTo:nil];
[query countObjectsInBackgroundWithBlock:^(int number, NSError * error) {
count = number;
[aCountView addSubview:self.generateCountLabel];
if (count > 0){
[aView setUserInteractionEnabled:YES];
[aView setEnabled:YES];
}
}];
}
Then you can call...
[self queryForKey:#"note" view:self.note countView:self.noteCount];
[self queryForKey:#"image" view:self.pic countView:self.picCount];
If you firm up your naming you can use dynamic object selectors, i.e. for the 'note' one you have #"note", self.note and self.noteCount so you could take the #"note" and select both the note and noteCount views dynamically (as they both start with 'note'), however this wouldn't work for your image one as you have #"image" but then self.pic and self.picCount.
UPDATE
Rename image to pic and then expose the four views (picCount, pic, note and noteCount) as properties. Then you can use something like this...
- (void)queryForKey:(NSString *)aKey  {
    PFQuery * query = [PFQuery queryWithClassName:#"Vote"];        
    query.cachePolicy = kPFCachePolicyNetworkElseCache;
    [query whereKey:#"poll" equalTo:self.vote];
    [query whereKey:aKey notEqualTo:nil];
    [query countObjectsInBackgroundWithBlock:^(int number, NSError * error, NSString *aKey) {
[self setValue:number forKey:aKey];
UIView *countView = [self objectForKey:[NSString stringWithFormat:#"%#Count", aKey]];
    [countView addSubview:self.generateCountLabel];
        if (number > 0){
UIView *mainView = [self objectForKey:aKey];
            [mainView setUserInteractionEnabled:YES];
            [mainView setEnabled:YES];
        }
    }];
}
You will have to play around with it as I don't have your full class definition to get it exactly right.

MapKit blue dot not visible when using custom annotations

I am not able to see the Blue current location dot when I use custom annotations
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id<MKAnnotation> ) annotation {
   MKAnnotationView *customAnnotationView=[[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil] autorelease];
   UIImage *pinImage = [UIImage imageNamed:#"ann.png"];
   [customAnnotationView setImage:pinImage];
   customAnnotationView.canShowCallout = YES;
                                                                                               
//UIImageView *leftIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ann.png"]];
//customAnnotationView.leftCalloutAccessoryView = leftIconView;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customAnnotationView.rightCalloutAccessoryView = rightButton;
   return customAnnotationView;
}
if (annotation == map.userLocation) {
return nil;
}
Add this.:d
I got the answer now. Just need to add the following lines to the above code at the end just before return customAnnotationView;
if (annotation ==
mapView.userLocation) {
NSLog(#"nil"); return nil; }
thanks :)
The visibility of the current user location "blue dot" is unrelated to custom annotations. To make the user's current location show, you need to set the showsUserLocation property of your MKMapView to YES. For example:
yourMapView.showsUserLocation = YES;
or:
[yourMapView showsUserLocation] = YES;
Understand that there is a quirk in the way MapKit displays the current user location: in the simulator the UserLocation will always be Apple's headquarters in Cupertino, CA, USA. It will work fine on the device, however.
Edited to add:
As Terente points out, you do have to be careful not to "eat" the user's location annotation, and so must test to see if the annotation you're processing is the user's location. I wrap the logic with:
if ([annotation isKindOfClass:[MapLocation class]]) {
}
Where MapLocation is my annotation class.

Why is my code leaking?

UPDATE2 I think I found the true source of the leaks. I had some business objects that have string properties I forgot to release. These string properties were copied from my custom xlm node object, created here (KGYXMLNode) I don't understandt why the leak is reported here instead of my custom class. My NSString properties were copy and not retain.
UPDATE: I think it was a bug in Instruments or something or it doesn't magically leak anymore, but since xcode 4 it doesn't show this leak.
Hello, according to instruments i have a leak in the following code. I've built an objective-c wrapper around certain libxml functions to be able to parse xml docs using xpath, and in this method I'm setting the innerText for my custom node object.
-(void) SetInnerTextForNode: (xmlNodePtr) node : (KGYXMLNode *) obcNode
{
if ((node) && (node->children))
{
for (xmlNodePtr pnode = node->children; pnode != NULL; pnode = pnode->next)
{
if (pnode->type == XML_TEXT_NODE)
{
xmlChar *content = pnode->content;
NSString *innerText = [[NSString alloc] initWithUTF8String: (char *)content];
NSString *trimmedText = [innerText stringByTrimmingCharactersInSet: trimCharSet];
if (trimmedText.length > 0)
obcNode.innerText = trimmedText;
[innerText release];
break;
}
}
}
}
The leak is NSString *innerText = [[NSString alloc] initWithUTF8String: (char *)content];. I don't know what is wrong.
You shouldn't access a node's content directly, instead use xmlNodeGetContent:
        xmlChar *content = xmlNodeGetContent(pnode);
        NSString *innerText = [[NSString alloc] initWithUTF8String: (char *)content];
        NSString *trimmedText = [innerText stringByTrimmingCharactersInSet: trimCharSet];
        if (trimmedText.length > 0)
          obcNode.innerText = trimmedText;
        [innerText release];
        // you must free what xmlNodeGetContent returns!
        xmlFree(content);
        break;
I don't know why your code is leaking, but it seems to me that you have an unsafe assignment of an autoreleased object to obcNode.innerText without retaining it.
This is a bit of a guess, but I think your dealloc method for obcnode does not release its innerText instance variable on deallocation. At first glance, your code fragment looks fine for memory management and that is the only potential error I can see.
The reason why it would be flagging the leak for innerText is possibly that trimmedText uses the same underlying unichar array as innerText but with different start and length values and therefore it retains innerText to stop the unichar array from going away.
Because trimmedText is an immutable string, sending copy to it merely causes it to send retain to itself and return itself, so obcNode owns trimmedText which owns innerText.