Pages

Tuesday, May 13, 2014

Detect User take Screenshots when app is active


Many a times it may happen that during iOS application development, we may require to know if user has taken any screenshot in the application’s active state or not. We may consider it as a security reason or as a feature of iOS app to inform the user that you have taken a snap of application.

In iOS6  or ealier when a screenshot is taken, it cancels all the touches on the screen. So using this technique, you can detect the screenshots. All you have to do is, implement the UIView touches cancel method or the UILongPressGestureRecognizer method and
you have to make user touch the screen. So when user will take screenshot, the touch by the user will get cancelled and the UIView touchesCancel method (or long press action method with cancel state) will be called. So in that method, you can take the relevant steps to protect your data.

Lets first see how can implements this

    •    In the AppDelegate.m class add Long press gesture to the window in the     application’s didFinishLaunching method.
    •    Considering user has touched the screen. Now when the screenshot will be taken, the touch will be cancelled and the long press action method will be called with the cancelled state.
    •    But you have to keep in mind that the touch can also be cancelled when the state of the application will resign the active state. So for this, you can maintain the state of the application and accordingly work around. You can take a flag and set/reset it based on application’s state and use that flag in the long press action method. If it is TRUE, then only consider the screenshot detection.
    •    Here is the implementation,

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;

    self.isActive = YES; // this flag will indicate whether the application is in active state or not

    UILongPressGestureRecognizer * gest = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    gest.minimumPressDuration = 0.1;
    [self.window addGestureRecognizer:gest];

    [self.window makeKeyAndVisible];
    return YES;
}

- (void)longPress:(UIGestureRecognizer *)gest {

    if (gest.state == UIGestureRecognizerStateCancelled && self.isActive) {
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Detected" message:@"You have captured a screenshot!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
    }

}

- (void)applicationWillResignActive:(UIApplication *)application
{
    self.isActive = NO;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.isActive = YES;
}

This solution will work on all iOS version but not in iOS 7. In all the iOS versions below iOS 7, the active touches are getting cancelled whenever the screenshot is taken. But now in the latest released iOS 7, the active touches are no longer getting cancelled so this technique is not work. However, iOS 7 provides a brand-new notification for this event: UIApplicationUserDidTakeScreenshotNotification. Just subscribe to it as usual to know when a screenshot was taken.Notification will be posted when user presses Home + Sleep to print screen.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidTakeScreenshot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];

  return YES;
}

- (void)userDidTakeScreenshot:(NSNotification *)notification
{

    NSLog(@"userDidTakeScreenshot");
}

but disadvantage of this method is fire after the screen sort is capture.

Sunday, May 11, 2014

Difference between nil vs Nil

They are all zeros, the difference lies in their types

-> The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
 NSNull is a class for objects that represent null.

-> nil is an id. So its points to a non-existent objective-c object

-> Nil is a non-existent objective-c class

-> [NSNull null] is an object that’s meant to stand in for nil in situations where nil isn’t allowed. For example, you can’t have a nil value in an NSArray. So if you need to represent a “nil”, you can use [NSNull null]
Also there is no ‘null’ in the objective c its ‘NULL’ not ‘null’. ‘null’ exist in Java or in C# not in Objective-C

nil -> Null-pointer to objective- c object
NIL -> Null-pointer to objective- c class
null-> null value for C pointer.
NSNUll -> Singleton object used to represent null.

NSNull     [NSNull null]     singleton object used to represent null

nil is the literal null value for Objective-C objects, corresponding to the abstract type id or any Objective-C type declared via @interface. For instance:
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;

if (anotherObject == nil) // do something

Nil is the literal null value for Objective-C classes, corresponding to the type Class. Since most code doesn’t need variables to reference classes, its use is not common. One example is:

 Class someClass = Nil;
 Class anotherClass = [NSString class];

Resize image without loss in quality

- (UIImage*)resizeImage:(UIImage*)aImage reSize:(CGSize)newSize;
{
    UIGraphicsBeginImageContextWithOptions(newSize, YES, [UIScreen mainScreen].scale);
    [aImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

How to change the colour of a UITextField's placeholder text for iOS7



Working with UITextFields is generally quite easy, you can customise most attributes apart from the placeholder text, while you can obviously change the text you can't change the colour of the text or it's position. This was a problem we had on a recent project, our design required us to have UITextFields with black backgrounds, the placeholder text colour is dark grey which is almost invisible in our app and Apple provides no easy way to change this.


We solved this by subclassing UITextField and overriding drawPlaceholderInRect: method to draw our own placeholder text. This is fairly straight forward in iOS6 but did not work as expected in iOS 7.




- (void)drawPlaceholderInRect:(CGRect)rect
{  
 UIColor *colour = [UIColor lightGrayColor]
if ([self.placeholder respondsToSelector:@selector(drawInRect:withAttributes:)]
{
     // iOS7 and later
     NSDictionary *attributes = @{NSForegroundColorAttributeName: colour, 
     NSFontAttributeName: self.font};
     CGRect boundingRect = [self.placeholder boundingRectWithSize:rect.size 
     options:0 attributes:attributes context:nil];  
             [self.placeholder drawAtPoint:CGPointMake(0, (rect.size.height/2)
      -boundingRect.size.height/2) withAttributes:attributes];
    }else{
// iOS 6
        [colour setFill];
[self.placeholder drawInRect:rect withFont:self.font
        lineBreakMode:NSLineBreakByTruncatingTail 
alignment:self.textAlignment]: 
       } 
}