Showing posts with label objective-c. Show all posts
Showing posts with label objective-c. Show all posts

02 September 2014

Objective-c delegates

It is a long time I since I stopped working on iPhone and objc.

But some collage is working and we was discussing about objc delegates and what is it and how it is related to categories.

Following is an example illustrate how things going from Categories to Delegates.


// NSObject+TurnLights.h
// a Category on NSObject to allow any subclass to turn on/off lights
@interface NSObject (TurnLights)

-(void) turnLightsOn;
-(void) turnLightsOff;

@end

//Lights.m
// this is the lights class that delegate its work to some object (of type id) to do the on/off instead of itself
@implementation Lights

@synthesize id delegate;

-(void) doLightings{
      [delegate turnLightsOn];
      [delegate turnLightsOff];
}
@end


//MyContorller.m
// is my controller class that decided to be a delegate for the Lights class

#import "NSObject+TurnLights.h"

@implementation MyController

-(void) btnClicked:(id) sender{
      Lights* lights = ...
      [lights setDelegate: self];
}

-(void) turnLightsOn{
      NSLog("turnLightsOn");
}

-(void) turnLightsOff{
      NSLog("turnLightsOff");
}
@end

05 March 2013

cellForRowAtIndexPath best implementation

After working with cellForRowAtIndexPath in more than a project, it appears that the best implementation (performance-wise) is the following:


CellIdentifier = [NSString stringWithFormat:@"cell%@", @"some_term_per_page"];
cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
                
SomeData* data = [self data:indexPath.row];
        
if ([[cell.contentView subviews] count] > 0)
      [[[cell.contentView subviews]objectAtIndex:0]removeFromSuperview];
        
[cell.contentView addSubview:[DrawingHelper cellView:data]];

24 July 2012

08 October 2011

The easier way to create Tabbed Bar in iPhone

I see the easier way to create a UITabBar in iPhone, is through the Controller.

Only create the View yourself, if you want to customize it, otherwise, don't go that way!

Suppose we have a button that we click to open a TabBar with two UITabBarItems, as usual , we push the next controller to the UINavigationConroller ... but this time we will push a UITabBarController..

Here's the code with inline comments:


References:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UITabBarController_Class/Reference/Reference.html#//apple_ref/occ/cl/UITabBarController



07 October 2011

ObjectMapper an Objective-c lib to map data structure into user-objects

I was working on iPhone project and I needed to consume data from some JSON service.

I've tried to find some library to convert returned JSON String into my own custom objects... but I didn't.

Most popular JSON libraries (JSONKit, SBJson, etc ..) just convert JSON String into Objective-c data structures (NSDictionary, NSArray). So I decided to write a lib to convert from NSDictionary and NSAarry into my own custom-objects.

ObjectMapper [https://github.com/MuhammadHewedy/ObjectMapper] is a project used to convert NSDictaionry to Custom user objects. It can used with JSON parsing libraries (JSONKit, SBJSON, etc) to convert the returned NSDictionary and NSArray into custom user objects

Example usage:

Complete Example project found here : https://github.com/MuhammadHewedy/ObjectMapper/tree/master/ObjectMapperTester
Good luck!

01 October 2011

Centralize your NSURLConnection code while using Async connections

We should use Aysnc calls when dealing with NSURLConnections. May articles illustrate why we should do that, among them is this one The truth about synchronous NSURLConnection. Also see my question on SO. But We want also to have our "Communicate" code grouped somewhere not to be implemented by all of our classes in the project. This post is talking about how to solve this issue.. Thanks to AliSoftware . Well, We will have some Utility class the doing the connection and handle the data for us.. but what will we do when we got the data from the server? we should call some method on the caller class (in cases, it is a ViewContoller).. so we should send the target class and the selector to be called when the connection done receiving data. So, Here's the code (quick and dirty) for the URLCaller class:
  1. 
  2. #import <Foundation/Foundation.h>
  3. 
  4. @interface URLCaller : NSObject
  5. {
  6.     NSMutableData* data;
  7.     NSObject* target;
  8.     SEL selector;
  9. }
 10. @property (nonatomic, retain) NSMutableData* data;
 11. @property (nonatomic, retain) NSObject* target;
 12. @property (nonatomic) SEL selector;
 13. 
 14. -(id) initWithTarget:(NSObject*) target selector:(SEL)selector;
 15. -(void) call:(NSString*) url;
 16. 
 17. @end
 18. 
 19. 
 20. #import "URLCaller.h"
 21. 
 22. @implementation URLCaller
 23. @synthesize data, target, selector;
 24. 
 25. -(id) initWithTarget:(NSObject*) _target selector:(SEL)_selector
 26. {
 27.     if (self = [super init])
 28.     {
 29.         self.target = _target;
 30.         self.selector = _selector;
 31.     }
 32.     return self;
 33. }
 34. 
 35. -(void) call:(NSString*) url
 36. {
 37.     NSURLConnection* connection = [[NSURLConnection alloc]initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:self];
 38.     [connection release];
 39. }
 40. 
 41. #pragma mark - NSURLConnection deleages
 42. 
 43. -(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
 44. {
 45.     data = [[NSMutableData alloc] init]; // _data being an ivar
 46. }
 47. -(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)_data
 48. {
 49.     [self.data appendData:_data];
 50. }
 51. -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
 52. {
 53.     // Handle the error properly
 54. }
 55. -(void)connectionDidFinishLoading:(NSURLConnection*)connection
 56. {
 57.     NSString* stringData = [[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]autorelease];
 58.     [target performSelector:selector withObject:stringData];
 59. }
 60. 
 61. - (void)dealloc 
 62. {
 63.     [target release];
 64.     [data release];
 65.     [super dealloc];
 66. }
 67. 
 68. @end
And in the caller class (in my case is a ViewController), we will use the URLCaller class:
  1. 
  2. -(IBAction)getDataFromServer:(id)sender
  3. {
  4.     URLCaller* caller = [[URLCaller alloc]initWithTarget:self selector:@selector(setTextViewContents:)];
  5.     [caller call:@"http://search.twitter.com/search.json?q=Muhammad"];
  6.     [caller release];
  7. }
  8. 
  9. // this will got called when the data returned from the server
 10. -(void) setTextViewContents:(NSString*) contents
 11. {
 12.     text.text = contents;
 13. }
You can get the project source code from here Very important notice is that, the application will never got freeze while the data is being transferred, and this is what we wants!

18 September 2011

Building and installing NSJSONSerialization on gnustep to parse JSON data

I was seeking for a JSON Parser for Objective-c on gnustep runtime..
Thanks to sudo rm -rf he directed me to use the source code from gnustep repository .

I got the source code for Three Files NSJSONSerialization.h, NSJSONSerialization.m and GSFastEnumeration.h, although not worked directly, I've did very small modifications

Steps to use:

Note: Steps below are executed on Mingw and should be used with little or no modifications on Linux.
  1.  Go and download the archive that contains the modified Three files from here.
    put them into a directory say in your home folder with the following path: ~/objc/json
  2. cd ~/objc/json and issue the following command to build the files:
    gcc -c `gnustep-config --objc-flags` *.m
    If no errors reported, this means the build process succeed. and the object file has been generated.
  3. Now let's put this files inside the gnustep installation, to do so, mv the the .h files NSJSONSerialization.h and GSFastEnumeration.h to /GNUstep/System/Library/Headers/Foundation
  4. Now let's create a static library and put it inside gnustep libraries path:
    Use the following command:
    ar q libNSJSONSerialization.a NSJSONSerialization.o Then move the generated libNSJSONSerialization.a file to /GNUstep/System/Library/Libraries/
Note that, we now copied two .h files and one .a file into gnustep installation directories. 
You now safe to remove all the directory ~/objc/json and all of its contents.

Now You are done installing the NSJSONSerialization as a static lib into gnustep.

Now let's write a test program. Now create a brand new directory into your home directory say ~/objc/json_test and create a file named json_main.m in this directory.
Put the following code in it:

  1. #import <Foundation/Foundation.h>
  2. #import <Foundation/NSJSONSerialization.h>
  3. 
  4. int main(void)
  5. {
  6.     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
  7. 
  8.     NSDictionary* dictionary = [NSDictionary dictionaryWithObjects:
  9.                 [NSArray arrayWithObjects: @"Muhammad", @"26", @"2011", @"Cairo, Egypt", 
 10.                 [NSArray arrayWithObjects: @"Arabic", @"English", nil] , nil]
 11.                                                             forKeys: 
 12.                 [NSArray arrayWithObjects: @"name", @"age", @"year", @"address", @"language", nil]];
 13.     NSError* error;
 14.     NSData* data = [NSJSONSerialization dataWithJSONObject: dictionary
 15.                 options:NSJSONWritingPrettyPrinted
 16.                 error: &error];
 17.     if (error)
 18.     {
 19.         NSLog(@"ERROR %@", error);
 20.     }else
 21.     {
 22.         NSString* jsonString = [[NSString alloc] initWithData: data 
 23.                                         encoding: NSASCIIStringEncoding];
 24.         NSLog(@"%@", jsonString);
 25.                     
 26.         [jsonString release];        
 27.     }
 28. 
 29.     [pool release];
 30.     return 0;
 31. }
Now use the following command to compile it:
gcc `gnustep-config --objc-flags` *.m -L /GNUstep/System/Library/Libraries -lNSJSONSerialization -lobjc -lgnustep-base 
[The inclusion for the libraries should be exactly in this order]

Now run:
$ a.exe
2011-09-18 01:35:49.726 a[5696] {
"language": [
        "Arabic",
        "English"
        ],
"year": "2011",
"name": "Muhammad",
"age": "26",
"address": "Cairo, Egypt"
}

Congratulations! you can use gnustep to parse json data.

Disclaimer: This article is distributed in the hope that it will be useful, but without any warranty. Use it on your own.

13 September 2011

NSData wraps array of bytes (8bits) so beware when use it

SA, Objc NSData object wraps array of bytes so you should send the size parameter properly.. suppose you want to wrap an array of a custom struct Emp.. you have to specify the size of the Array as number of bytes as following: sizeof(StructType)* array_length See the following example carefully:
  1. #import <Foundation/Foundation.h>
  2. 
  3. int main(void)
  4. {
  5. 
  6.     NSAutoreleasePool* pool = [NSAutoreleasePool new];
  7. 
  8.     typedef struct
  9.     {
 10.         char* name;
 11.         int   hiredate;
 12.     }Emp;
 13.     
 14.     Emp emps[] = {{"Mouhammad", 2010}, {"Moutaz", 2010}, {"Ahmad", 2010}};
 15.     
 16.     NSData* data = [NSData dataWithBytes : emps length: sizeof(Emp) * 3 ];    // here we specify the number of BYTES to be holded
 17.     
 18.     Emp* newEmps = [data bytes];
 19.     int count = [data length]/ sizeof(Emp);            // here we go the number of bytes holded, 
 20.                                             //watch the division of the total number of bytes
 21.                                             // over the size of each struct element
 22.     
 23.     int i=0;
 24.     for (; i< count; i++)
 25.     {
 26.         Emp e = *newEmps;
 27.         NSLog(@"%s %i", e.name, e.hiredate);
 28.         newEmps++;
 29.     }
 30.     
 31. 
 32.     [pool release];
 33.     return 0;
 34. }

12 September 2011

The power of Objective-c categories.. add category for NSData object

Categories is a very powerful feature in objective-c.. we will show how to use it to overrides the function "description" of the NSData object in the following example:
#import <Foundation/Foundation.h>
#import "../../mem.h"

@interface NSDate(description)
-(NSString*) description;
@end

@implementation NSData(description)
-(NSString*) description
{
    int len = [self length];
    char buff[len];
    [self getBytes: buff];
    
    NSMutableString* ret = [NSMutableString string];
    
    int i;
    for (i=0; i < len; i++)
        [ret appendFormat: @"%i ", buff[i] ];
    
    return ret;
}
@end

int main(void)
{
    POOL;
    char arr[]= {10, 20, 30};
    
    NSData* data = [NSData dataWithBytes:arr length: sizeof(arr)/sizeof(char)];
    
    NSLog(@"%@", [data description]);

    _POOL;
    return 0;
}
Note, POOL and _POOL are two macros defined in "../../mem.h" as follow: #define POOL NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] #define _POOL [pool drain]

How to determine the amount of memory required by my char* in struct?

Suppose you have the following C struct:
  1. typedef struct
  2. {
  3.     char* name;
  4. }Emp;
I asked in SO on how to determine the amount of memory to allocate to the char* struct member. and the answer was to use lazy/delayed allocation as of:
  1. void setName(Emp* emp, char* newName)
  2. {
  3.     free(emp->name);
  4.     emp->name = malloc(strlen(newName) + 1);
  5.     strcpy(emp->name, newName);
  6. }
(It seems to me to be the same idea used for Objective-C, the setter is release the previous pointer and then retain (in C to copy) the parameter pointer. So, the whole program will be:
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. 
  5. typedef struct
  6. {
  7.     char* name;
  8. }Emp;
  9. 
 10. void init(Emp** emp)
 11. {
 12.     *emp = malloc(sizeof(Emp));
 13.     (*emp)->name = NULL;
 14.     (*emp)->name = malloc(sizeof(char*));
 15. }
 16. 
 17. void release(Emp** emp)
 18. {
 19.     free((*emp)->name);
 20.     free(*emp);
 21. }
 22. 
 23. void setName(Emp* emp, char* newName)
 24. {
 25.     free(emp->name);
 26.     emp->name = malloc(strlen(newName) + 1);
 27.     strcpy(emp->name, newName);
 28. }
 29. char* getName(Emp* emp)
 30. {
 31.     return emp->name;
 32. }
 33. 
 34. int main(void)
 35. {
 36.     Emp* emp;
 37.     init(&emp);
 38.     setName(emp, "Muhammad                              Abdullah");
 39.     printf("%s", getName(emp));
 40.     release(&emp);
 41.     
 42.     return 0;
 43. }

11 September 2011

What if you forgot to deallocate reserved memory in your objective-c (c/c++) programs?

The worst thing ever that I usually do is to forget to deallocates memory for objects I create when working with non-garbage collector languages (like C/C++/Objective C) So, That If I didn't de-allocate the memory .. what in that?? Actually it is a disaster ... Watch this example:
  1. #import <Foundation/Foundation.h>
  2. 
  3. int main(void)
  4. {
  5.     long long i;
  6.     for (i=0; i < 100000000000000; i++)
  7.     {
  8.         NSString* string = [[NSString alloc] initWithString :@"string"];
  9.         //[string release];
 10.     }
 11. 
 12.     [NSThread sleepForTimeInterval: 5];
 13.     
 14.     return 0;
 15. }
Then compile and run with GNUstep, the memory used by the program reaches 2 GB (I've 4 GB of RAM), and then the program terminates printing:
Virtual memory exhausted

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Remember, each time you enter a block of code (method for example) and allocate the miss to deallocate the memory you allocate will add this to the RAM and will not remove..finally you may find your program get crashed because it uses too much memory !

10 September 2011

Wrappers in Objective-c

  1. //string_2_primtiives.m
  2. #import <Foundation/Foundation.h>
  3. 
  4. /**
  5. *    You can convert the following to each other
  6. *    NSNumber <=> primitives <=> NSString 
  7. */
  8. 
  9. int main(void)
 10. {
 11.     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 12. 
 13.     //1- primitives => NSNumber
 14.     NSNumber* intNum = [NSNumber numberWithInteger: 20];
 15.     NSNumber* floatNum = [NSNumber numberWithFloat: 25.325];
 16.     
 17.     NSLog(@"%@ %@", intNum, floatNum);
 18.     
 19.     // 2- NSNumber => primitives:
 20.     int x = [intNum intValue];
 21.     float f = [floatNum floatValue];
 22.     // also, we can convert nay number object (regards of which value it contains) to any primitives type
 23.     //, and the standard C casting rules will be applied:
 24.     int x2 = [floatNum intValue];
 25.     
 26.     NSLog(@"%d %g %d", x, f, x2);
 27.     
 28.     // 3- primitives => NSString:
 29.     NSString* string = [NSString stringWithFormat: @"%d",x];
 30.     NSLog(@"%@", string);
 31.     
 32.     // 4- NSString = > primitives:
 33.     int i = [@"1" intValue];
 34.     float g = [@"13.4" floatValue];
 35.     int i2 = [@"13.4" intValue];
 36.     
 37.     NSLog(@"%d %g %d", i, g, i2);
 38.     
 39.     // 5- NSNumber => NSString
 40.     NSString* str = [NSString stringWithFormat:@"%@", [NSNumber numberWithBool:20]];
 41.     NSLog(@"%@", str);
 42.     
 43.     // 6- NSString => NSNumber 
 44.     NSNumber* charNum = [NSNumber numberWithChar: [@"20" intValue]];
 45.     NSLog(@"%@", charNum);
 46.     
 47.     [pool release];
 48.     return 0;
 49. }
 50. 
 51. /** output:
 52. 
 53. 20 25.325
 54. 20 25.325 25
 55. 20
 56. 1 13.4 13
 57. 1
 58. 20
 59. 
 60. */

26 August 2011

Class methods in Java vs Objective-C

The are not the same!

Yes, although their usage is the same (singleton methods, factory methods, utility methods)

But actually class methods in ObjC is looks like instance methods. but in java they are t treated differentially than instance methods ..

Watch this example in Java (in seconds we will write it in ObjC and compare the results):


  1. 
  2. public class Abc
  3. {
  4.     public static void main(String[] args)
  5.     {
  6.         B.func();
  7.         // 1- B will inherit `func() from A.
  8.         // 2- `func()` call the method `x()`
  9.         // 3- since `func()` is a static method in Class A, it will reference non-qualified methods as static methods in the same class
 10.         // 4- `func()` will call `x()` from the same class it resids in (class A)
 11.     }
 12. }
 13. 
 14. class A
 15. {
 16.     static void x()
 17.     {
 18.         System.out.println("in A");
 19.         
 20.     }
 21.     
 22.     static void func() 
 23.     {
 24.         x(); // as if we call : A.x();
 25.     }
 26. }
 27. 
 28. class B extends A
 29. {
 30.     static void x()
 31.     {
 32.         System.out.println("in B");
 33.         
 34.     }
 35. }

Will print : in A

Now lets see how Objective C treat the same situation:


  1. //A.h
  2. #import <Foundation/Foundation.h>
  3. 
  4. @interface A : NSObject
  5. 
  6. +(void) x;
  7. +(void) func;
  8. 
  9. @end
 10. 
 11. @implementation A
 12. +(void) x
 13. {
 14.     NSLog(@"in A");
 15. }
 16. +(void) func
 17. {
 18.     [self x];
 19. }
 20. 
 21. @end


  1. //B.h
  2. #import <Foundation/Foundation.h>
  3. #import "A.h"
  4. 
  5. @interface B : A
  6. 
  7. +(void) x;
  8. 
  9. @end
 10. 
 11. @implementation B
 12. 
 13. +(void) x
 14. {
 15.     NSLog(@"in B");
 16. }
 17. 
 18. @end


  1. //Main.m
  2. #import <Foundation/Foundation.h>
  3. #import "B.h"
  4. 
  5. int main(void)
  6. {
  7. 
  8.     [B func];
  9. 
 10.     return 0;
 11. }

Will Print: in B

Conclusion:
class methods in Objective-C differ from Java.
In Java, class methods don't override each other but hide each other. Also, class methods which comes in no context (when don't being called in any other object), it calls the methods in the same class regardless whom object is calling it.
In Objective C, the existence of self keyword in the class methods make it possible to call functions based on the caller itself (self returns to the object/class that calls the function).

19 August 2011

Setting up mintty in GNUStep (mingw)

SA,

In the last post, we have talked about how to install GNUStep on Linux.
Similar but yet more simple steps provided here to install GNUStep on Windows.

Okey you can follow the steps in the previous link and you will get GNUStep installed for you on Windows..

If you are very comfortable with the "Ugly" windows CMD window, don't continue reading..

but if you hate the look and feel of the CMD window, do what i did .. install "mintty".

So the following will be the steps to install and configure mintty.
1- open "All Programs > GNUstep > Shell"
write the following to install mintty:

mingw-get install mintty

Now Right click on the desktop and then "New > shortcut" and then type in the box the following

C:\GNUstep\msys\1.0\bin\mintty.exe /bin/env CHERE_INVOKING=1 /bin/bash -l


Now click Next then Finish.

You are done.. try to open the shortcut now :)
.

18 August 2011

Installing Objective-C on Linux

SA,

In a previous post we have seen how to compile and run Objective-c programs on ubuntu linux..

If we used NextSTEP framework .. we need to follow steps here :
Installing and Using GNUstep and Objective-C on Linux
a very good tutorial ..

17 August 2011

Step-by-step running Objective-c on Ubuntu Linux for Windows users

SA,

In this post, I'll try to compile and run the code in this Objective-c Wikibook lesson

If you are using M$ Windows, go download VMWare Player from here and then download ubuntu Linux, I am using version 10.04.. you can get some recent version if you like..

There are variety of tutorials online to help you install ubuntu on vmware.. it is a very trivial task..


Once you have your ubuntu distribution up and running (either a VM or a standalone installation)... keep reading ...

Ubuntu linux (and almost all linux distro) come with Parts of GCC (GNU Compiler Collections) pre-installed.

Let's test the existence of a C compiler. Now type in the command line the following command:

cat <<EOF>hello.c
#include<stdio.h>
int main(void){printf("In the name of Allah\n");}
EOF

And Then:
gcc -o hello hello.c && ./hello


If you find the following output printed on the console window, then we are going in the right direction:
In the name of Allah



Now let's install the Objective-c compiler into the GCC (it is about 4MB):
Open synaptic (from command line `sudo synaptic` [will prompted for your password]

Now search for "objc" in synaptic.. and then install the package "libobjc2".


Now we are ready...

Let's try to compile and run the example in the wikibooks link we have talked about before..

First create a directory in your home directory called "objc"
and then put the three files below in it

Here's the interface Point:

//Point.h
#import <objc/Object.h>

@interface Point : Object
{
@private
    double x;
    double y;
}

-(id) x: (double) x_value;
-(double) x;
-(id) y: (double) y_value;
-(double) y;
-(double) magnitude;

@end


(note, return to the wikibooks link if you need to understand the code)

And here's the implementation class:

//Point.m
#import "Point.h"
#import <math.h>

@implementation Point
    -(id) x: (double) x_value
    {
        x = x_value;
        return self;
    }

    -(double) x
    {
        return x;
    }

    -(id) y: (double) y_value
    {
        y = y_value;
        return self;
    }

    -(double) y
    {
        return y;
    }

    -(double) magnitude
    {
        return sqrt(x*x + y*y);
    }

@end

And now the Test file:


//Test.m
#import "Point.h"
#import <stdio.h>

int main(void)
{

    Point *p = [[Point alloc] init];
    [p x:10.0];
    [p y:20.0];
    printf("The Distance from Point %g to %g is %g\n", [p x], [p y], [p magnitude]);
    return 0;
}

Now let's compile the above program..
The easiest way to do so is to execute the following command from the same directory where these files exist (objc directory)

gcc -o Test *.m -lobjc -lm

Note, the `-lm` is required only because we use the math.h library.
now let's execute the program:
./Test 
The Distance from Point 10 to 20 is 22.3607


That's all.. hope that you find this post helpful..