Saturday, January 10, 2015

nil

nil -  это ничто. Но если с пристрастием подойти к этому ничто, то и трактат сочинить можно. А эпиграф такой взять:
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. Tone Hoare.

(Изобретение нулевого указателя - это моя ошибка на миллиард долларов. Энтони Хоар) 
Энтони Хоар, всемирно известный ученый (например, тем, что изобрел QuickSort), еще в 1965 году ввел в обиход null и, как выясняется, считает это своей ошибкой.

В языке С с нулем все естественно: 0 для простых значений, NULL - для указателей. То есть:
int x = 0;
int *p = NULL;
И сам NULL определен в stddef.h как:
#define NULL ((void*)0)
Удобный способ отметить указатель, который не указывает на конкретный адрес в памяти. malloc возвращает нулевой указатель, когда не удается выделить память. Обращение по нулевому указателю вызовет Segmentation Fault или Access Violation.
Подразумевается, что 0, встреченный там, где по контексту подразумевается указатель, будет замене компилятором на нулевой указатель. NULL используется с точки зрения лучшего стиля программирования.
Можно еще один ноль упомянуть - это ASII ноль: '\0', NUL, с одним L:
#define NUL '\0'
В С++11 добавился nullptr. Это новое ключевое слово (keyword), которое нужно использовать вместо NULL.
Программисты на С традиционно хотят знать больше о внутреннем представлении кода. И в этом "нулевом случае" можно  продолжать выяснять подробности до бесконечности. Сейчас меня больше Objective-C интересует. 
В Objective-C, в дополнение к 0 и NULL, есть nil для указателей на объект. А также Nil для указателя на класс. На уровне Foundation framework появляется класс NSNull, в котором метод +null возвращает синглтон (singleton) на экземпляр NSNull. И это уже не ничто. Скорее, нечто.
Согласно традициям С-программистов выясним детали. В файле objc.h определен nil и Nil:


#ifndef Nil
# if __has_feature(cxx_nullptr)
#   define Nil nullptr
# else
#   define Nil __DARWIN_NULL
# endif
#endif

#ifndef nil
# if __has_feature(cxx_nullptr)
#   define nil nullptr
# else
#   define nil __DARWIN_NULL
# endif

#endif

__DARWIN_NULL объявлен в _type.h:
#define __DARWIN_NULL ((void *)0)

То есть, Nil и nil - это С-шный нулевой указатель. Наверное, основная цель добавления - улучшение стиля. В Objective-C нулевому указателю на объект можно посылать сообщения. Это особенность языка, но говорят об этом так, как будто, в самом nil есть что-то особенное и что nil-у можно посылать сообщения. Креша, как в случае С/С++, не будет. Если вызвать метод у nil, то метод вернет нулевое значение. Звучит так, будто бы это отличия nil от NULL.
Зачем добавили класс NSNull? В Cocoa коллекции не могут содержать нулей. NSNull - это класс, это уже не нулевой указатель и его можно сохранить в коллекции:
        NSArray *array = @[ @1, @2, [NSNull null], @4];
        NSLog(@"array: %@", array);
Консоль показывает:
array: (
    1,
    2,
    "<null>",
    4

)
И почему изобретение NULL ошибка? Можно представить язык программирования без нулевых указателей?

Friday, January 9, 2015

Objective-C: @compatibility_alias

I've never heard about @compatibility_alias compiler directive. I found it on NSHipster.
Here is a small test:
#import <Foundation/Foundation.h>

@interface Test : NSObject
@end

@implementation Test
@end

@compatibility_alias ATest Test;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        ATest *test1 = [[ATest alloc] init];
        NSLog(@"%@", test1);
        
        Test *test2 = [[Test alloc] init];
        NSLog(@"%@", test2);
    }
    return 0;
}

Friday, May 9, 2014

iOS: Is phone number valid

How to checkt that a phone number is valid?

Simply check if it contains only ciphers and few symbols such as '+', '-', '(' and ')'. Method IsPhoneValid below demonstrates this way.

But my app is running on an iPhone. Is it possible that the iOS SDK does not have any standard way to validate a phone number?
So how UITextView detects the phone number?

Method named IsPhoneNumber valid demonstrates another way to verify the phone number:

Saturday, March 22, 2014

UIImage: loading, decompressing

Here is a very nice article:
Avoiding Image Decompression Sickness
I liked the part explaining the memory usage for an image:
Looking at memory used an image takes multiple chunks of it:
1. space on disk or being transferred over the internet
2. uncompressed space, typically width*height*4 Bytes (RGBA)
3. when displayed in a view the view itself also needs space for the layer backing store

The function presented in this article loads an image:

This function decompress the image:

Saturday, March 8, 2014

Objective-C: Array Sorting

The following program shows how to sort an array of people with descriptors and using comparator:
Console:
2014-03-08 19:10:28.489 Sorting[84868:303] unsorted: (
    "Einshtein Albert",
    "Napoleon Bonapart",
    "Kutozov Michail",
    "Zhukov Georgiy",
    "Nabokov Vladimir",
    "Nikulin Yuri",
    "Nietzsche Friedrich"
)
2014-03-08 19:10:28.491 Sorting[84868:303] sortedArrayUsingDescriptors: (
    "Einshtein Albert",
    "Kutozov Michail",
    "Nabokov Vladimir",
    "Napoleon Bonapart",
    "Nietzsche Friedrich",
    "Nikulin Yuri",
    "Zhukov Georgiy"
)
2014-03-08 19:10:28.491 Sorting[84868:303] sortedArrayUsingComparator: (
    "Einshtein Albert",
    "Kutozov Michail",
    "Nabokov Vladimir",
    "Napoleon Bonapart",
    "Nietzsche Friedrich",
    "Nikulin Yuri",
    "Zhukov Georgiy"
)

Program ended with exit code: 0

Saturday, December 21, 2013

Cool NSExpression

Just for fun:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSExpression *expression = [NSExpression expressionWithFormat:@"(2 + 2) * 2"];
        id value = [expression expressionValueWithObject:nil context:nil];
        
        NSLog(@"4 + 5 - 2**3 == %f", [value floatValue]);
    }
    return 0;

}

Console:
2013-12-21 19:36:38.404 Expression[56749:303] (2 + 2) * 2 == 8.000000

Or a bit more complicated:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSExpression *expression = [NSExpression expressionWithFormat:@"2 + 2 ** 3"];
        id value = [expression expressionValueWithObject:nil context:nil];
        
        NSLog(@"2 + 2 ** 3 == %f", [value floatValue]);
    }
    return 0;

}

Console:
2013-12-21 19:37:18.340 Expression[56763:303] 2 + 2 ** 3 == 10.000000

Or even evaluate a formula:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
     
        NSExpression *expression = [NSExpression expressionWithFormat:@"2 * x + 4 * y"];
        id value = [expression expressionValueWithObject:@{ @"x": @2, @"y" : @4} context:nil];
        NSLog(@"result = %f", [value floatValue]);
    }
    return 0;

}

Console:
2013-12-21 19:55:32.572 Expression[56795:303] result = 20.000000

Calculate an average of numbers:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
     
        NSArray *arrNumbers = @[@3, @6, @3, @8, @4, @12, @9, @11];
        
        NSExpression *expression = [NSExpression expressionForFunction:@"average:" arguments:@[[NSExpression expressionForConstantValue:arrNumbers]]];
        id value = [expression expressionValueWithObject:nil context:nil];
        
        NSLog(@"average of numbers 3, 6, 3, 8, 4, 12, 9, 11 is %f", [value floatValue]);
    }
    return 0;

}
Console:
2013-12-21 19:51:15.771 Expression[56781:303] average of numbers 3, 6, 3, 8, 4, 12, 9, 11 is 7.000000

Let's calculate a deviation of numbers:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
     
        NSArray *arrNumbers = @[@3, @6, @3, @8, @4, @12, @9, @11];
        NSExpression *expression = [NSExpression expressionForFunction:@"stddev:" arguments:@[[NSExpression expressionForConstantValue:arrNumbers]]];
        id value = [expression expressionValueWithObject:nil context:nil];
        NSLog(@"deviation of numbers 3, 6, 3, 8, 4, 12, 9, 11 is %f", [value floatValue]);
    }
    return 0;

}

Console:
2013-12-21 19:46:14.628 Expression[56772:303] deviation of numbers 3, 6, 3, 8, 4, 12, 9, 11 is 3.316625

Thursday, December 19, 2013

Objective-C: Serialize to JSON

Since iOS 5 serialization to JSON is pretty simple:

This sample above, where a dictionary (attributes) is saved in an ASCII file, demonstrates all major rules:
1. An dictionary (or an array) can be converted to a JSON object.
2. This array or dictionary may contain NSString, NSNumber, NSValue, NSArray or NSDictionary objects.

It's even simpler to deserialize such JSON file. For example, this Mac OS command line app will read and parse the json-file created in the previous app:

File "json_file.json" should be in the same folder where the executable is. For an iOS application this json-file can be added to the project and read from the app bundle:
NSString *fileName = [[NSBundle mainBundle] pathForResource:@"json_file" ofType:@"json"];