Dailycode.info

Short solution for short problems

Tech: My Techorama 2015 review

1.           ASP.NET 5

1.           ASP.NET 5

A session on the new ASP.NET 5. A lot of overlapping information. New features of visual studio 2015. This session also confirms that WEB API is the way to go in the future.

Here is a summary of the foundational improvements:

  • New light-weight and modular HTTP request pipeline
  • Ability to host on IIS or self-host in your own process
    • Showed in the session, you can host is from command line on USB stick.
  • Built on .NET Core, which supports true side-by-side app versioning
  • Ships entirely as NuGet packages
    • Not part of the System.Web.dll anymore.
  • Integrated support for creating and using NuGet packages
  • Single aligned web stack for Web UI and Web APIs
  • Cloud-ready environment-based configuration
  • Built-in support for dependency injection
  • New tooling that simplifies modern Web development
  • Build and run cross-platform ASP.NET apps on Windows, Mac and Linux
  • Open source and community focused

 

2.           The internet of your things (Iot)

Mainly about Azure and the capabilities to host applications on Azure. Interesting was the table storage. You can create a table service where different types of data can be stored in 1 table. It’s a no SQL datastore. This is ideal for storing structured non relational data.

Link to this:

https://azure.microsoft.com/en-gb/documentation/articles/storage-dotnet-how-to-use-tables/

 

3.           How to live longer and happier with Visual Studio 2015

This session was about the new features of Visual Studio 2015.

You can see that a lot of resharper functionality is now default in VS 2015.

Also integration with a BOWER, Gulp and Grunt are used very frequenly. For packages like AngularJS, bower is better than NuGet.

http://www.dotnetcurry.com/visualstudio/1096/using-grunt-gulp-bower-visual-studio-2013-2015

 

 

4.           EF7, Who are You and What Have You Done With My ORM?

Julie Lerman who gave the session is an expert on EF. She wrote books and gives trainings about it. Her conclusion in regard with the silver bullet key note is that the best way to go for the future is:

-       Keep using EF 6.0 in existing projects.

-       Start using EF 7.0 in new projects.

EF7 is a complete makeover of the entity framework. Since the start of EF they continued on the same code base. For EF7 they restarted completely from the beginning, to make it more light weight and also to tackle some challenges that were not possible to take with the old code base.

 

5.           "Write once, run anywhere”: Can AngularJS & Cordova do it?

This was definitely my favorite session. Christian Weyer explained in 1 hour and 30 min the complete lifecycle of a modern app that has 1 code base but can be published in any device!

 

He is co-owner of thinktecture that tackle very large implementations using .Net back-end, HTML5 and Javascript to code once, deploy anywhere.

 

Their code base is EF --> .Net WEB API --> AngularJS.

Using Cordova they can deploy the code to native iOS, Android and Windows Phone.

Then the AngularJS is also available in any browser and can even be build to native Apps for Windows and Mac OS.

 

6.           "It's alive!": Real-time applications with ASP.NET SignalR and AngularJS

Again a great session by Christian Weyer. SignalR is definitely something to look into. Very brief it’s a way to let the server communicate to the clients. E.g. when some data is updated and the clients need to refresh without the user having to click on a refresh button.

More info:

http://signalr.net/

 

7.           HTML 5 Security

This session was mainly about CORS and ways that javascript could inject bad code. If setup the code in the correct way, you could prevent this.

 

8.           Aurelia Deep Dive

This session was about an alternative to AngularJS. Another javascript framework. The demo were not impressive, some failed. I do not believe in Aurelia, since the community behind it is not comparable with AngularJS.

 

9.           Domain Driven Design for the Database Driven-Mind

Another view on application architecture. This looks promising, but at the moment not feasible because lack of knowledge and high impact on development. Also we are in a process of change that first need to be advanced.

 

10.        The Engaging User Experience & the Natural User Interface

Key note about user experience. Not very interesting. Talking a lot about xbox Kinect and face recognition.

 

11.        Chrome developer tools

Here is a good summery made by one of the attendees:

The Console tab

It’s probably safe to assume that you all know and use the Console Tab of Google Chrome to write your debug statements and evaluate JavaScript expressions. Most of the time we do that by using “console.log” statement which writes your logging messages to the console. If you are using a lot of those “console.log” statements in your code then things can quickly get messy and it will become difficult to work through your logs to find the one line you actually need.

To organize your statements you can use “console.groupCollapsed” and “console.groupEnd”. These functions will create a collapsable group in the log window so you can find your debug lines faster.


If you want to measure how fast your code is executing you can use “console.time” and “console.timeEnd”. This can also prove quite handy when you want to benchmark certain functions.


Device Emulation

The Device Emulator enables you to test out your website on several devices (phones, tablets, computers…) and on different network speeds (4G, 3G, GPRS…). This makes it very easy to test out your responsive design. The emulator even supports touch events!

You can enable/disable it by toggling the device icon Chrome Dev Tools - Mobile Iconin your Dev Tools.


The Network tab

The Network tab is used to monitor the performance of your application and helps you identify slow loading resources. It includes detailed timing data, HTTP request and response headers, cookies…

A very useful feature of the Network tab is that you can download its contents to a .HAR file. This could help us debug the “unreproducible bugs” reported by a QA Engineer. If he’s doing his tests with the Network tab opened he can just send the failed requests to a developer to investigate. All he has to do is right-click the network table and select “Save as HAR with Content”. This will download a .HAR-file that can be read using a tool called Chrome HAR Viewer.

Quick tips

Inline editing

To enable inline editing just open up the console and type “document.body.contentEditable = true” and press ENTER. You can now modify any text on your page by just typing into the browser window. If you have to build a multilingual application you can use this to easily test what would happen if the text in your title or menu items would be translated (and thus be longer or shorter than intended by the designer).

Blackbox scripting

You all know that you can debug javascript code by adding breakpoints to your code in the “sources tab”. Very often this tab includes a lot of scripts that you don’t care about (external libraries etc.). You can prevent the debugger from breaking in those scripts by “blackboxing” them. Just right-click on the file and select “Blackbox Script”. You can stop blackboxing a script by right-clicking the same file and selecting “stop blackboxing”.

Styling log statements

You can add CSS styling to your “console.log” statements. This can prove useful if you want something to stand out if it occurs.


Conclusion

Please note that this blogpost is just a high level overview of useful and time saving features that were presented by Shay Friedman (@ironshay) at Techorama. The Google Chrome dev tools contain a lot more functionality than what can be covered here. If you are curious to learn more or want to read on about the topics covered in this post you can visit https://developer.chrome.com/devtools.

 

12.        Decomposing AngularJS

This was an interesting session that gave a deeper view of how the AngularJS binding works. He actually created a fresh JavaScript Framework from scratch (using code blocks and copy paste) that bound model to the view.

 

13.        EF7 demo demo demo

This was a replacing session were Julie showed EF 7 in combination with ASP.NET 5 in action.


iOS: Check if device is iPad or not

I have some screen that have different behaviour depending if its an iPad or not. Because iPad screen is a lot larger,  for iPhone I sometimes use a sub screen to lookup certain data, as for on the iPad I can keep it on screen. Not to easily check for iPad add these two lines to your class, or if used in different classes add it to your precompiled header file:

#define IDIOM    UI_USER_INTERFACE_IDIOM()

#define IPAD     UIUserInterfaceIdiomPad

Now you can check for iPad like this:

if (IDIOM == IPAD)

{

    iPad      

}

else

{

    iPhone

}


.Net WebAPI: add time zone suffix to datetime in JSON

On iOS, my JSON formatter needed to have the UTC format for date times. But My .Net WebAPI by default just formatted the date like this:

"timeStamp":"2015-01-04T00:00:00"

now just by adding these lines to the WebApiConfig.cs:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;

the date times got the correct format:

"timeStamp":"2015-01-04T00:00:00Z"


iOS: How to add a precompiled header file

Sounds stupid, since before this was default behaviour. Now a project starts without. Adding can sometimes be a pain, since just adding the file is not enough. 

This post helped me to the solution, although I head to change 1 more thing.

So the thing was to open the Build settings in xcode of your target. You will see a search box on the upper right corner.

Search for: GCC_PRECOMPILE_PREFIX_HEADER and set it to Yes.

Next search for: GCC_PREFIX_HEADER and add the name of the file including the extension ".pch".

Now it was still not compiling, because the file was not in the root directory of where the project file was, but rather in a subdirectory. So I had to put in the value:

MyProgram/MyProgramPrefixHeader.pch

Now everything compiled again and the prefix header is loaded!


iOS: Unhandled exception handling

Application crashes are very frustrating, especially if you do not know what happened. Lets says a memory problem on an old iPad 2 or recently we had a missing storyboard, but the app only crashed when archived and deployed, not when we were debugging. Probably some files were not cleaned and still  there in debug mode. Anyway, a very easy way to capture any unhandled exception is to add this small piece of code to your app delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    NSSetUncaughtExceptionHandler(&onUncaughtException);

Then add the onUncaughtException method and do whatever you want to do with it. I write the error to the internal DB, so later I can see on the client what happened.

void onUncaughtException(NSException* exception)

{

  NSLog(@"uncaught exception: %@", exception.description);

  NSArray *backtrace = [exception callStackSymbols];

  NSString *version = [[UIDevicecurrentDevice] systemVersion];

  NSString *message = [NSStringstringWithFormat:@"OS: %@.\nSummary:%@\nBacktrace:\n%@",

                       version,

                       exception.description,

                       backtrace];

  

  [DBStoreCreateErrorLog:@"Uncaught exception occurred"AndText:message];

}


iOS: Navigate back to root view controller then navigate away in one action.

There are several ways to reach this goal. The goal being to navigate from any view controller in the navigation controllers view controller collection, back to the root view controller and then forward to another controller. Why, because sometimes you want the back of you're new view controller to be the root view controller and not the previous controller. In my case I end an editing proces and the user has to be directed back to the edit template overview page. But when the user then pushes back, he needs to end up in the root view.

So here's the code, what we are doing it simple, just alter the list of view controller from the navigation controller:

        NSArray *viewControllers = senderVC.navigationController.viewControllers;

        NSMutableArray *newViewControllers = [NSMutableArray array];

        

        // preserve the root view controller

        [newViewControllers addObject:[viewControllers objectAtIndex:0]];

        // add the new view controller

        UIStoryboard * sb = [UIStoryboardstoryboardWithName:@"TemplatesStoryboard"bundle:nil];

        UIViewController * vcTo = [sb instantiateInitialViewController];

        [newViewControllers addObject:vcTo];

        // animatedly change the navigation stack 

        [senderVC.navigationController setViewControllers:newViewControllers animated:YES];

First we take the root view controller from the index 0, then add it to our newviewcontroller array. Next just init your second view, were you want the user to end up and add it to the newviewcontrollers array. Last we set the current view controller which has to be in the navigation controllers view controllers collection.

This piece of code is called from a top menu action, that is added dynamically to each view controller. This code does the trick!


UIButton with gradient background and image on it!

I got a request for an app with lots of gradient styles on all kinds of controls.

When I applied the typical code to the UIButton, the text stayed on but the image disappeared.

So I found that the solution is to bring the UIImageview to the front like this:

[vw bringSubviewToFront:vw.imageView];

Now the complete code to make the UIButton look like this:

is this:

+ (void) MakeNormalButton:(UIButton *) vw

{

    CAGradientLayer *gradient = [CAGradientLayerlayer];

    gradient.frame = vw.bounds;

    gradient.colors = [NSArrayarrayWithObjects:(id)[[UIColorwhiteColor] CGColor], (id)[[UIColorlightGrayColor] CGColor], nil];

    [vw.layer insertSublayer:gradient atIndex:0];

    vw.layer.masksToBounds = NO;

    vw.layer.shouldRasterize = YES;

    [vw.layersetShadowColor:[UIColorblackColor].CGColor];

    [vw.layersetShadowOpacity:0.5];

    [vw.layersetShadowRadius:2.0];

    [vw.layersetShadowOffset:CGSizeMake(2.0f, 2.0f)];

    [vw.layersetCornerRadius:5.0f];

    [vw bringSubviewToFront:vw.imageView];

 

}


iOS: Picture editor (zooming, drawing, ...) complete code

I needed a view controller that could edit an image. But not just edit, also zoom in and out on the image and moving the image in the canvas.

So I created a separate XIB file with view and a view controller. It's working perfect. The first version was without zoom, so it resized the image to the screen size. In this case we always lost the resolution of the image.

So first a little demo with some pictures:

After taking the picture with the camera, a thumbnail appears in the picture list. By clicking on it, we are redirected to the picture edit screen. This is done on the 'didSelectItemAtIndexPath' method of the collection view (code see below following picture):

 

The code to accomplish this is reasonably simple. I get the asset based on the picture URL that is saved in the collection view item:

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

    if(showZones==NO)

    {

        ImageThumbView * cell = (ImageThumbView *)[collectionView cellForItemAtIndexPath:indexPath];

        typedef void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *asset);

        typedef void (^ALAssetsLibraryAccessFailureBlock)(NSError *error);

 

        Picture * p = [picturesForProject objectAtIndex:indexPath.row];

        

        ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)

        {

            ALAssetRepresentation *rep = [myasset defaultRepresentation];

            CGImageRef iref = [rep fullResolutionImage];

 

            if (iref)

            {

                @try {

                    self.img = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:(UIImageOrientation)[rep orientation]];

                    [StoryBoardNavigation NavigateToChangePictureStoryboard:selfAndPicture:self.imgAndPictureObject:cell.pic];

                }

                @catch (NSException *exception) {

                    NSLog(@"Exception:%@",exception);

                    [cell.imgImage setImage:[UIImage imageNamed:@"error.png"]];

                }

            }

            else

            {

                [cell.imgImage setImage:[UIImage imageNamed:@"error.png"]];

            }

        };

        

        ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)

        {

            NSLog(@"can't get image");

        };

        NSURL *asseturl = [NSURL URLWithString:p.picture_url];

        [assetslibrary assetForURL:asseturl

                       resultBlock:resultblock

                      failureBlock:failureblock];

    }

 

}

 

Here the code to call the picture edit, so here you actually provide the PictureEdit view controller with a image object:

+(void) NavigateToChangePictureStoryboard:(UIViewController *) vc AndPicture:(UIImage *) image AndPictureObject:(Picture *) pic

{

    PictureEditVC * vcTo = [[PictureEditVCallocinitWithNibName:@"PictureEditVC"bundle:nil];

    vcTo.imageForMainView = image;

    vcTo.pic = pic;

    [UIViewtransitionWithView:vc.viewduration:0.8options:UIViewAnimationOptionTransitionCrossDissolve

                    animations:^{

                        [vc.navigationController pushViewController:vcTo animated:NO];

                    }

                    completion:NULL];

 

 

}

Now we end up on the picture edit screen. On top you see 3 buttons, the first on the left saves the images if there were changes made. The second on the left cancels the changes. The button on the right switches between zooming and editing. Below the zooming mode is set, you can zoom by using the pinch gesture and you can move the picture with the pan gesture.

Before we edit, we click on the edit button, and you'll see the different color buttons appear. 

We click on the red button and draw the little red heart on the image.

Now lets zoom in. Click on the edit button to go to zoom mode and zoom in:

Now we click again on the edit button to edit and draw some yellow hearts:

Zoom out again and save:

If you look closely the thumbnail reflects the changes. A copy of the changed image is also saved in the library.

Before we look into the code of the view controller that does all the work, first thing is to create a XIB.

Create the XIB file with the view controller. The xib file is very simple and could look like this:

 

I provide 2 properties (Basically you only will need the first). The first is the image to edit, the second is the picture object with the url of the picture (I use this to store the picture reference in the local DB), if we change the picture, we will change the picture objects url.

The .h file of the picture edit view controller is very simple:

//

//  PictureEditVC.h

//  LocationReport

//

//  Created by Mark Deraeve on 03/06/14.

//  Copyright (c) 2014 AssistU. All rights reserved.

//

 

#import <UIKit/UIKit.h>

#import "Button.h"

#import "Picture.h"

 

@interface PictureEditVC : HomeVC <UIScrollViewDelegate>

 

@property (weak, nonatomic) IBOutlet Button *btnEdit;

@property (weak, nonatomic) IBOutlet Button *btnUndo;

@property (weak, nonatomic) IBOutlet Button *btnSave;

 

@property (weak, nonatomic) IBOutlet UIButton *btnYellow;

@property (weak, nonatomic) IBOutlet UIButton *btnGreen;

@property (weak, nonatomic) IBOutlet UIButton *btnRed;

@property (weak, nonatomic) IBOutlet UIButton *btnBlack;

 

@property (weak, nonatomic) UIImage * imageForMainView;

 

@property (weak, nonatomic) Picture * pic;

 

 

@end

It just has the outlets for the buttons and the image property and the picture object property. (You can easely change the type Button to UIButton, it's only for layout purpose.

Now all you need is the implementation file:

//

//  PictureEditVC.m

//  LocationReport

//

//  Created by Mark Deraeve on 03/06/14.

//  Copyright (c) 2014 AssistU. All rights reserved.

//

 

#import "PictureEditVC.h"

#import <AssetsLibrary/AssetsLibrary.h>

 

@interfacePictureEditVC ()

 

@end

 

@implementation PictureEditVC

{

    bool drawActive;

    CGPoint cumTranslation;

    CGFloat red;

    CGFloat green;

    CGFloat blue;

    CGFloat brush;

    CGFloat opacity;

    CGRect pageRect;

    UIImage * initImage;

    UIImageView * tempDrawImage;

    UIImageView * mainImageView;

    UIScrollView * scrollView;

    bool mouseSwiped;

    CGPoint lastPoint;

    CGPoint scaleLastPoint;

}

 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        // Custom initialization

    }

    returnself;

}

 

- (void)viewDidLoad

{

    [superviewDidLoad];

     [GeneralFunctionsMakeSelectedButton:self.btnBlack];

}

 

-(void) viewDidAppear:(BOOL)animated

{

    // Do any additional setup after loading the view from its nib.

    tempDrawImage.userInteractionEnabled =YES;

    cumTranslation = CGPointMake(0,0);

    

    drawActive = NO;

    red = 0.0/255.0;

    green = 0.0/255.0;

    blue = 0.0/255.0;

    

    brush = 3.0;

    opacity = 1.0;

    

    mainImageView.contentMode = UIViewContentModeScaleAspectFit;

    if (self.imageForMainView)

    {

        mainImageView = [[UIImageViewalloc] initWithImage:self.imageForMainView];

        pageRect = CGRectMake(0, 0, self.imageForMainView.size.width, self.imageForMainView.size.height);

        //mainImageView.image = self.imageForMainView;

    }

    else

    {

        pageRect = self.view.frame;

        pageRect.origin = CGPointMake(0,0);

        mainImageView = [[UIImageViewalloc] initWithFrame:pageRect];

    }

    

    tempDrawImage =[[UIImageViewalloc] initWithFrame:pageRect];

    

    scrollView = [[UIScrollViewalloc] initWithFrame:pageRect];

    scrollView.delegate = self;

    scrollView.minimumZoomScale = 0.3;

    scrollView.maximumZoomScale = 3.0;

    

    [scrollViewsetBackgroundColor:[UIColorredColor]];

    

    scrollView.contentSize= pageRect.size;

    

    [scrollViewaddSubview:mainImageView];

    [scrollViewaddSubview:tempDrawImage];

    [scrollViewsendSubviewToBack:mainImageView];

    

    [self.view addSubview:scrollView];

    [self.viewsendSubviewToBack: scrollView];

    

    UIPanGestureRecognizer *Scrolling  = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onScroll:)];

    UIPinchGestureRecognizer *Zooming   = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onZoom:)];

    UITapGestureRecognizer *Tap   = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];

    

    [scrollView addGestureRecognizer:Scrolling];

    [scrollView addGestureRecognizer:Zooming];

    [scrollView addGestureRecognizer:Tap];

}

 

#pragma mark Zoom / Draw

 

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView

{

    return tempDrawImage;

}

 

- (void)onTap:(UIPinchGestureRecognizer*)sender

{

    if (drawActive)

    {

        UIGraphicsBeginImageContext(tempDrawImage.frame.size);

        [tempDrawImage.image drawInRect:CGRectMake(0, 0, tempDrawImage.frame.size.width, tempDrawImage.frame.size.height)];

        

        CGPoint currentPoint = [sender locationInView:tempDrawImage];

        

        CGPoint scalePoint;

        scalePoint.x = currentPoint.x*scrollView.zoomScale;

        scalePoint.y = currentPoint.y*scrollView.zoomScale;

        

        CGRect borderRect = CGRectMake(scalePoint.x, scalePoint.y, brush, brush);

        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);

        CGContextSetLineWidth(context, brush);

        CGContextFillEllipseInRect (context, borderRect);

        CGContextStrokeEllipseInRect(context, borderRect);

        CGContextFillPath(context);

        

        CGContextFlush(UIGraphicsGetCurrentContext());

        tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        

        //Draw dot.

        

    }

}

 

- (void)onZoom:(UIPinchGestureRecognizer*)sender

{

    if (!drawActive)

    {

        sender.view.transform = CGAffineTransformScale(sender.view.transform, sender.scale, sender.scale);

        sender.scale = 1;

    }

}

 

- (void)onScroll:(UIPanGestureRecognizer*)sender

{

    if (drawActive==NO)

    {

        CGPoint translation = [sender translationInView:self.view];

        sender.view.center = CGPointMake(sender.view.center.x + translation.x,

                                         sender.view.center.y + translation.y);

        [sender setTranslation:CGPointMake(0, 0) inView:self.view];

        cumTranslation = CGPointMake(cumTranslation.x + translation.x,

                                     cumTranslation.y + translation.y);

    }

    else

    {// Processing the drawing by using comparing:

        if (sender.state == UIGestureRecognizerStateBegan)

        { /* drawing began */

            

            mouseSwiped = NO;

            

            lastPoint = [sender locationInView:tempDrawImage];

            scaleLastPoint.x = lastPoint.x*scrollView.zoomScale;

            scaleLastPoint.y = lastPoint.y*scrollView.zoomScale;

            

        }

        else if (sender.state == UIGestureRecognizerStateChanged)

        { /* drawing occured */

            mouseSwiped = YES;

            

            CGPoint currentPoint = [sender locationInView:tempDrawImage];

            

            CGPoint scalePoint;

            scalePoint.x = currentPoint.x*scrollView.zoomScale;

            scalePoint.y = currentPoint.y*scrollView.zoomScale;

            

            UIGraphicsBeginImageContext(tempDrawImage.frame.size);

            [tempDrawImage.image drawInRect:CGRectMake(0, 0, tempDrawImage.frame.size.width, tempDrawImage.frame.size.height)];

            CGContextMoveToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);

            CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), scalePoint.x, scalePoint.y);

            CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);

            CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );

            CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);

            CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

            

            CGContextStrokePath(UIGraphicsGetCurrentContext());

            tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();

            [tempDrawImage setAlpha:opacity];

            UIGraphicsEndImageContext();

            

            scaleLastPoint = scalePoint;

        }

        else if (sender.state == UIGestureRecognizerStateEnded)

        { /* drawing ended */

            if(!mouseSwiped) {

                UIGraphicsBeginImageContext(tempDrawImage.frame.size);

                [tempDrawImage.image drawInRect:CGRectMake(0, 0, tempDrawImage.frame.size.width, tempDrawImage.frame.size.height)];

                CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);

                CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);

                CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, opacity);

                CGContextMoveToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);

                CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);

                CGContextStrokePath(UIGraphicsGetCurrentContext());

                CGContextFlush(UIGraphicsGetCurrentContext());

                tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();

                UIGraphicsEndImageContext();

            }

        }

    }

}

 

#pragma mark Button events

 

- (IBAction)btnEditClicked:(id)sender

{

    drawActive = !drawActive;

    self.btnBlack.hidden = !drawActive;

    self.btnGreen.hidden = !drawActive;

    self.btnRed.hidden = !drawActive;

    self.btnYellow.hidden = !drawActive;

    if (drawActive==YES)

    {

        [self.btnEdit setTitle:[[VariableStore sharedInstance] Translate:@"$PO$Zoom"] forState:UIControlStateNormal];

    }

    else

    {

        [self.btnEdit setTitle:[[VariableStore sharedInstance] Translate:@"$PO$Draw"] forState:UIControlStateNormal];

    }

}

- (IBAction)btnYellowClicked:(id)sender

{

    red = 255/255.0;

    green = 255.0/255.0;

    blue = 0.0/255.0;

    [self SetClicked:self.btnYellow];

}

- (IBAction)btnGreenClicked:(id)sender

{

    red = 0.0/255.0;

    green = 255.0/255.0;

    blue = 0.0/255.0;

    [self SetClicked:self.btnGreen];

}

- (IBAction)btnRedClicked:(id)sender

{

    red = 255.0/255.0;

    green = 0.0/255.0;

    blue = 0.0/255.0;

    [self SetClicked:self.btnRed];

}

- (IBAction)btnBlackClicked:(id)sender

{

    red = 0.0/255.0;

    green = 0.0/255.0;

    blue = 0.0/255.0;

    [self SetClicked:self.btnBlack];

}

 

-(void) SetClicked:(UIButton *) btn

{

    [GeneralFunctions MakeSimpleButton:self.btnBlack];

    [GeneralFunctions MakeSimpleButton:self.btnRed];

    [GeneralFunctions MakeSimpleButton:self.btnYellow];

    [GeneralFunctions MakeSimpleButton:self.btnGreen];

    [GeneralFunctions MakeSelectedButton:btn];

}

 

- (IBAction)btnUndoClicked:(id)sender

{

    tempDrawImage.image = nil;

}

- (IBAction)btnSaveClicked:(id)sender

{

    if (tempDrawImage!=nil)

    {

        UIGraphicsBeginImageContext(mainImageView.frame.size);

        

        [mainImageView.image drawInRect:CGRectMake(0, 0, mainImageView.frame.size.width, mainImageView.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0];

        [tempDrawImage.image drawInRect:CGRectMake(0, 0, tempDrawImage.frame.size.width, tempDrawImage.frame.size.height) blendMode:kCGBlendModeNormal alpha:opacity];

        mainImageView.image = UIGraphicsGetImageFromCurrentImageContext();

        tempDrawImage.image = nil;

        UIGraphicsEndImageContext();

 

        //overwrite the picture in the picture library

        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

        [library writeImageToSavedPhotosAlbum:mainImageView.image.CGImage orientation:(ALAssetOrientation)mainImageView.image.imageOrientation completionBlock:^(NSURL *assetURL, NSError *error )

         {

             if (self.pic)

             {

                 self.pic.picture_url = [NSString stringWithFormat:@"%@", assetURL];

                 [DBStore SaveContext];

             }

         }];

        [self.navigationController popViewControllerAnimated:YES];

    }

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

@end

 

Want to try this yourself, you could lose the Picture stuff, just provide the image to the view controller. Copy paste the code, with some easy fixes it should run perfectly. If needed, I could provide a demo project.


iOS: UITextField in UICollectionView get behind keyboard.

OK, I already posted a solution to move the view up when the keyboard shows so your textfield or view is not behind, but on top of the keyboard. 

Recently I had a similar problem, but this solution was not working exactly is I wanted. The problem was that when clicked in a textfield that was located in the top of the collection view, the field got moved out of screen. 

The first and easy part is moving the view up when the keyboard shows, just by implementing the solution found on all forums registering the keyboardwilshow and hide notifications:

- (void)viewWillAppear:(BOOL)animated

{

    // register for keyboard notifications

    [[NSNotificationCenterdefaultCenter] addObserver:self

                                             selector:@selector(keyboardWillShow)

                                                 name:UIKeyboardWillShowNotification

                                               object:nil];

    

    [[NSNotificationCenterdefaultCenter] addObserver:self

                                             selector:@selector(keyboardWillHide)

                                                 name:UIKeyboardWillHideNotification

                                               object:nil];

}

 

- (void)viewWillDisappear:(BOOL)animated

{

    // unregister for keyboard notifications while not visible.

    [[NSNotificationCenterdefaultCenter] removeObserver:self

                                                    name:UIKeyboardWillShowNotification

                                                  object:nil];

    

    [[NSNotificationCenterdefaultCenter] removeObserver:self

                                                    name:UIKeyboardWillHideNotification

                                                  object:nil];

 

}

These 2 selectors simply move the view up or down, I made the move up function general:

//method to move the view up/down whenever the keyboard is shown/dismissed

+(void)setViewMovedUp:(BOOL)movedUp AndView:(UIView *) vw

{

    int movementDistance = 80; // tweak as needed

    if ( UIInterfaceOrientationIsLandscape([[UIApplicationsharedApplication]statusBarOrientation]))

    {

        movementDistance = kOFFSET_FOR_KEYBOARDHOR;

    }

    else

    {

        movementDistance = kOFFSET_FOR_KEYBOARDVER;

    }

    const float movementDuration = 0.3f; // tweak as needed

    

    int movement = (movedUp ? -movementDistance : movementDistance);

    

    [UIViewbeginAnimations: @"anim"context: nil];

    [UIViewsetAnimationBeginsFromCurrentState: YES];

    [UIView setAnimationDuration: movementDuration];

    vw.frame = CGRectOffset(vw.frame, 0, movement);

    [UIViewcommitAnimations];

 

}

So this function is called when the keyboard moves up or down like this:

-(void)keyboardWillShow

{

    [GeneralFunctionssetViewMovedUp:YES AndView:self.view];

 

}

 

-(void)keyboardWillHide

{

    [GeneralFunctionssetViewMovedUp:NOAndView:self.view];

 

}

This already works, but will shift the top textfields out of screen:

 

When clicked on one of the top fields, you can see the field moving out of screen, I clicked in the textfield with text menu, it's out of screen after the keyboard shows:

Now how to solve this. I had to find out when clicked in the collection view in a textfield that would appear behind the keyboard if shown.

To solve this I made a delegate function in the cell view controller that would be called when the textfield edit did begin. 

-(void) collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath

{

    selectedIndexPath = indexPath;

}

 

-(void) EditDidBegin:(UICollectionViewCell *)cell

{

    NSIndexPath * path = [self.colTranslations indexPathForCell:cell];

    [self SetMove:path];

}

 

-(void) SetMove:(NSIndexPath *) indexPath

{

    UICollectionViewLayoutAttributes *attributes = [self.colTranslations layoutAttributesForItemAtIndexPath:indexPath];

    

    CGRect cellRect = attributes.frame;

    

    CGRect cellFrameInSuperview = [self.colTranslations convertRect:cellRect toView:[self.colTranslations superview]];

    

    NSLog(@"%f",cellFrameInSuperview.origin.y);

    if (cellFrameInSuperview.origin.y > kOFFSET_FOR_KEYBOARDHOR)

    {

        moveScreen=YES;

    }

    else

    {

        moveScreen=NO;

    }

 

}

 

So the function SetMove will calculate where clicked in the superview and chooses if the keyboard needs to be shifted up or not.

Just add these checks to the selectors of the keyboard will show and hide notifications and it will work:

-(void)keyboardWillShow

{

    if (moveScreen==YES)

    {

        [GeneralFunctionssetViewMovedUp:YESAndView:self.view];

        up=YES;

    }

    else

    {

        up=NO;

    }

}

 

-(void)keyboardWillHide

{

    if (moveScreen==YES && up==YES)

    {

        [GeneralFunctionssetViewMovedUp:NOAndView:self.view];

    }

 

}

Now do not forget to declare the bool 

bool moveScreen;

 

bool up;

 
And the result is this:

You see the Menu field that was clicked is still visible.

Now if I click in a field that is behind the keyboard:

The screen moves up!

If you hide the keyboard, the screen will get back in its original position.


iOS: UITextView gets behind the keyboard

Very annoying problem when you make a simple view with on the bottom a UITextView. Reading a lot of solutions involving using a UIScrollview, I kept looking for an easy solution. And I found it.

The solution involves implementing the UITextView's delegate and moving up or down the view when the editing starts or ends.

Because the UITextView view doesn't have sent events like the UITextField, we need to implement the UITextViewDelegate .

Do not forget to set the delegate outlet for the TextView.

 

The rest is almost as easy:

#define kOFFSET_FOR_KEYBOARD 160.0

 

 

-(void) textViewDidBeginEditing:(UITextView *)textView

{

    if ([textView isEqual:self.txtRemark])

    {

        //move the main view, so that the keyboard does not hide it.

        if  (self.view.frame.origin.y >= 0)

        {

            [selfsetViewMovedUp:YES];

        }

    }

}

 

-(void) textViewDidEndEditing:(UITextView *)textView

{

    if ([textView isEqual:self.txtRemark])

    {

        if (self.view.frame.origin.y < 0)

        {

            [self setViewMovedUp:NO];

        }

    }

}

//method to move the view up/down whenever the keyboard is shown/dismissed

-(void)setViewMovedUp:(BOOL)movedUp

{

    [UIViewbeginAnimations:nilcontext:NULL];

    [UIViewsetAnimationDuration:0.3]; // if you want to slide up the view

    

    CGRect rect = self.view.frame;

    if (movedUp)

    {

        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard

        // 2. increase the size of the view so that the area behind the keyboard is covered up.

        rect.origin.y -= kOFFSET_FOR_KEYBOARD;

        rect.size.height += kOFFSET_FOR_KEYBOARD;

    }

    else

    {

        // revert back to the normal state.

        rect.origin.y += kOFFSET_FOR_KEYBOARD;

        rect.size.height -= kOFFSET_FOR_KEYBOARD;

    }

    self.view.frame = rect;

    

    [UIViewcommitAnimations];

}

 

We will edit the field remark:

After clicking in the field, the screen moves up:

When finished (by clicking the hide keyboard sign, or by editing another field, the screen moves down again.