Dailycode.info

Short solution for short problems

First app in the App Store !!!

Yesterday the Wiezer app got approved in the app store. For now only in Dutch, but I plan to release a multi language (English en Dutch) app with some improvements soon.

Here the first review of the app looking good! Check in AppStore!

First app is a special feeling, next would be a second app that could reach and interest the whole world.


iOS: Make a simple iOS7 ready button by subclassing UIButton

Very simple solution, but works like a charm.

Create a subclass of UIButton. 

There we overload the initFrame and important also the awakeFromNib:

- (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        // Initialization code

        [GeneralFunctionsMakeNormalButton:self];

    }

    returnself;

}

 

-(void) awakeFromNib

{

    [GeneralFunctionsMakeNormalButton:self];

 

}

 
This general function looks like this:

+ (void) MakeNormalButton:(UIView *) vw

{

    vw.backgroundColor= [UIColorwhiteColor];

    [vw.layersetCornerRadius:10.0f];

    [vw.layersetBorderColor:[UIColorblueColor].CGColor];

    [vw.layersetBorderWidth:1.0f];

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

    [vw.layersetShadowOpacity:0.5];

    [vw.layersetShadowRadius:2.0];

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

}

Now we also overwrite the setHighlighted method to show the button was selected:

-(void) setHighlighted:(BOOL)highlighted

{

    if (highlighted)

    {

        [selfhighLightView];

    }

    else

    {

        [selfcleanHighLightView];

    }

    [super setHighlighted:highlighted];

 

}

 

-(void) highLightView

{

    self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);

    self.layer.shadowOpacity = 0.25;

    self.backgroundColor= [UIColorblueColor];

}

 

-(void) cleanHighLightView

{

    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);

    self.layer.shadowOpacity = 0.5;

    self.backgroundColor= [UIColorwhiteColor];

}

 

Now you can change the class of your button in the storyboard designer to this class and your buttons get the new layout, no more programming todo.

 

Then from button less iOS 7 and button richt iOS 6 you get a uniform layout with very few changes. In the examples below, you'll see the iOS 6 layout on top, iOS 7 on the bottom.

 

 


iOS: Make your app react to connectivity change (iOS6)

* iOS7 see note at the end of this post first!

When you have an enterprise app, used for production follow up or something, were being online is crucial, connectivity loss or even a short fall out can bring frustrations and loss of data.

Using web services, the app will keep on working when there is no connection, simply throws errors when trying to fetch data or save data. To make the app more responsive, I build in a simple connectivity check so only offline functionality will be available.

To check if there is a WIFI or 3G connection, you can use the Reachability class given by Apple. I attached the file to this post: 

Reachability.h (3.63 kb)

Reachability.m (9.26 kb) 

You can also find it here: https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html

Now once you added the Reachability.h and .m file to your project, you can simply use this code to check for connectivity:

Add this variable to your view controller:

 Reachability *reachability;

Then in the view load initialise it and add a notifier to it, so your app is notified when there is a change in the connectivity:

 reachability = [ReachabilityreachabilityForInternetConnection];

 [reachabilitystartNotifier];

    

 [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(reachabilityDidChange:) name:kReachabilityChangedNotificationobject:reachability];

Now when the connectivity changes, the reachabilityDidChange is called:

- (void)reachabilityDidChange:(NSNotification *)notification

{

    [selfCheckInfo];

    NetworkStatus status = [reachabilitycurrentReachabilityStatus];

    

    if(status == NotReachable)

    {

        self.colVwDashBoard.backgroundColor = [UIColorredColor];

    }

    else if (status == ReachableViaWiFi || status == ReachableViaWWAN)

    {

        self.colVwDashBoard.backgroundColor = [UIColorcolorWithRed:204.0/255.0green:204.0/255.0blue:204.0/255.0alpha:1];

    }

 

}

What I'm doing, is check if there is WIFI or 3G and if not, I will make the collection view background red, you could disable all functionality that needs connection.

In fact thats all there is. Easy right?

 

After upgrading to iOS 7 on some devices, this implementation was not properly working, so I switched to AFNetworking class, I will post the easy implementation soon on this blog, I'll try to find time to work out a small and clear example.

When connection is lost, background turns red and only the camera icon will respond to clicks:

 

 

 

When connection is back, the background turns gray again:


iPad: Using a relative cheap device to power your business

As relative new iOS developer, I'm really exited about the posibilities that an iPad offers. You can power all kinds of business with this device.

I'm working now in a production environment, where the forklift drivers now use an iPad to move material. They can even control a weigh scale and weigh material from their forklift chair.

This is a little preview of the dashboard:

We use a shared .Net layer to power the back-end system, and through WCF services, I cennect the iPad to this system. Reusing almost all functionality, it only takes a short while to build the GUI in Apple's xcode environment. Incoming inspection, material location, taking pictures of material and uploading it to the server, looking up order information etc. 

I'm bursting out of ideas, just no time yet to create them all. My latest small project is called WIEZER. It's an companion app with a very popular card game. It keeps score, helps you put in score and leaving little chance for mistakes. Also rules are just 1 click away. The app is almost ready for deploying in the app store, guess when I have the time, I'll put it there for free!

Here you see the same base dashboard control coming back:

Some more childrens games etc that need some finishing touches.

I see a market in the smallest of companies up until large international companies back down to the home users.


iOS: FreeForm and UIScrollview: subviews do not react to scroll

After upgrading to iOS7 I've had some problems with a FreeForm combination with a UIScrollview.

First it didn't scroll at all, this was related to missing constraints. Then I noticed that some subviews were not sending their touches to the scrollview, or that the scrollview didn't react ot touches on subviews. 

After settings the 'Delays Content Touches' to YES, it worked again as normal.

What a relief.


iOS: Open second storyboard in modal with presentation curl.

I had a very large StoryBoard with a lot of relations. I started to group functionality and add the Views to different storyboards. Since iOS 7 and xcode 5 it came in a hurry, since the designer was crashing and messing up the layout.

First I just pushed the viewcontrollers in the navigation controller like this:

+(void) NavigateToCustomerLookupFrom:(UIViewController *)vc

{

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

    UIViewController * vcTo = [sb instantiateInitialViewController];

    

    [UIViewtransitionWithView:vc.viewduration:0.8options:UIViewAnimationOptionTransitionCrossDissolve

                    animations:^{

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

                    }

                    completion:NULL];

    

}

That worked. But then I came up with a views that needed to be opened in a modal way. So this is the code to do just that. In this example I use the partial curl effect to open it:

+(void) NavigateToSignatureFrom:(UIViewController *)vc withSignee:(NSString *) Signee

{

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

    UIViewController * vcTo = [sb instantiateInitialViewController];

    

    ((SignatureVC *) vcTo).Signee = Signee;

    

    [vcTo setModalTransitionStyle:UIModalTransitionStylePartialCurl];

    [vc presentViewController:vcTo animated:YEScompletion:nil];

}

The example also shows how to set properties of the destination controller.


iOS : Get the current date without time (eg: 2013/1/7 0:0:0)

I had to look for this a minute or 2. Its not that straight forward as .Net. You will have to use the NSDateComponents to create a date with only the year, month and day from the NSDate date. After serialization, the date looks like this: 2013-01-07T00:00:00.00.

Code:

NSDateComponents * dc = [[NSCalendarcurrentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDatedate]];

plan.ShiftDate = [[NSCalendarcurrentCalendar] dateFromComponents:dc];

 

 

 


Using nullable/nilable types with iOS

It's obvious that iOS doesn't support nilable or nullable(.Net) types. I started having problems becuase we have a .Net implementation (server side) where we have bool? So on client side it resulted in a YES/NO/N/A choice. In iOS its a Segmented Control that has these options. But when my Entities are converted to iOS objects, they result offcourse in simple types: bool. So this means that its by default no. How to solve this? I could change my objects on server side and regenerate them. But since I'm using the entity framework generation, I do not want to do this. Then my collegue pointed me in the good direction. Using partial classes on server side eventually did the trick. So by extending the base class and adding properties I got a working solution. I will describe it below with some points to pay attention to.

So on iOS site I want int in stead of bool. Int value 0 = YES, 1 = NO and 2 = null. To get this I created some methods on the .Net WCF services. Here is an example of the extension class I used:

public partial class GP_MES_F06ByOrder

{

    [DataMember]

    public int ICHolesNS

    {

        get

        {

            return GalvEntFunctions.GetIntFromBool(this.ICHoles);

        }

        set

        {

            this.ICHoles = GalvEntFunctions.GetBoolFromInt(value);

        }

    }

 

    [DataMember]

    public int ICDoubleWeldNS

    {

        get

        {

            return GalvEntFunctions.GetIntFromBool(this.ICDoubleWeld);

        }

        set

        {

            this.ICDoubleWeld = GalvEntFunctions.GetBoolFromInt(value);

        }

    }

 

The functions to convert the int to bool and bool to int I used:

public class GalvEntFunctions

{

    public static bool? GetBoolFromInt(int value)

    {

        switch (value)

        {

            case 0: return true;

            case 1: return false;

            default: return null;

        }

    }

 

    public static int GetIntFromBool(bool? value)

    {

        switch (value)

        {

            case true: return 0;

            case false: return 1;

            default: return 2;

        }

    }

}

Now these properties are available on you entities. Mind the name giving. Thats important. Because the serializer will serialize and deserialize in the order of the properties. So in my case cince I'm using it for iOS I added NS at the end to make sure this property is de/serialized after the original property. In my iOS client I only use the NS properties to get what I want.

Now you can use the default Entity generation without messing around in the code afterwards.

On iOS side I can now implement these nullable types very easy with my segmented controls:

    self.selOpeningHolesOK.selectedSegmentIndex = self.currentF06.ICHolesNS;

    self.selLoadingPosibilities.selectedSegmentIndex = self.currentF06.ICLoadingPos;


.Net Self Tracking Entities and JSON

I know this is not the ideal situation, better to use POCO's or simple objects. But when you already have a large structure in place using these self tracking entities, it can be usefull to do this. In my case we had webservices build for .Net client applications. Now we want to reuse this architecture and consume it on IPAD and IPHONE. Can this work? Yes offcourse. First I tried with SOAP, which works well, but there were 3 problems. First I was relying on a object generator tool of SUDZC, second SOAP is taking more data then JSON, third, iOS doesn't support nillable and the generator converted it into simple types. So now I decided to use JSON, use my own objects and reuse the webservices. 

This involved making a new service layer the consumes the same process layer as my .Net WCF services.

But you will notice that when you try to pass a self tracking entity in JSON format, the webservice will crash. 

The solution to this was:

Set the IsReference flag to false, and remove the DataMember attribute from the ChangeTracker.

//[DataMember]

public ObjectChangeTracker ChangeTracker

and

[DataContract(IsReference = false)]

public partial class GP_MES_Clients: IObjectWithChangeTracker, INotifyPropertyChanged

After this all is changed, you can consume this service in your iOS application!