Παρασκευή, 20 Απριλίου 2012

Add "holes" to an array - NSNull

You cannot add nil to an array.
If you need to add "holes" to an array, you must use NSNull.

 NSNull is an object that represents nil and is used specifically for this task. The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).

[array addObject: [NSNull null]];

source:
iOS programming - the big nerd ranch guide (3rd edition)
documentation

Τετάρτη, 11 Απριλίου 2012

How to pass arguments in object C - xcode programes


in Xcode:
  • Choose Produce from menu
  • Choose Edit Scheme
  • Select Run ApplicationName on the left
  • Select Arguments tab
  • Add Arguments with + on Arguments Passed on Launch




Challenge page 252 - solution - The Big Nerd Ranch Guide Objective C

The Big Nerd Ranch Guide - Objective C-  page 252 challenge


int spaceCount(char * sentence)
{
    int numOfSpaces =0;
    int i=0;
    
    if (sentence){                          //protection for NULL sentence
        while (sentence[i] != '\0'){
            if (sentence[i++] == ' ')
                numOfSpaces++;
        }
    }
    return numOfSpaces;
}


chars - c strings and NSString

notes from Big Nerd Ranch Guide - Objective C


CHAR
char = a byte could be treated as a number or a character. (0-127)

  • 0-31 ASCII - are unprintable control codes
  • 32 is the space character
  • 127 is the delete
The non-printable characters can expressed using escape sequences that start with \.
  • \0 = null byte (0x00)
C string
A C string is a series of characters right next to each other in memory. the string ends when the character 0x00 is encountered
  • char * test = malloc(5)
  • test[4]='\0'

String literals
You can create a pointer to a string of characters (terminated with the zero character) by putting the string in quotes.
  • char *start = "love";
DANGER: literals strings are CONSTANT. Don't try to change them!

To enable the compiler to warn you about writing to constant parts of memory, you can use the 
  • const modifier
  • const char * text= "test"; !Read-only variable is not assignable

C string to NSString
char *cstring = "ohmy!";
NSString *y = [NSString stringWithCstring:cstring encoding: NSUTF8StringEncoding];

NSString to C string
NSString *mystring = @"noway!";
const char *cstring = NULL;
        if ([mystring canBeConvertedToEncoding:NSUTF8StringEncoding]) {
            cstring = [mystring cStringUsingEncoding:NSUTF8StringEncoding];
        }

Κυριακή, 8 Απριλίου 2012

Bitwise operator OR and AND - in objective C - Exclusive OR - Complements - Shifting and Enum


  • | is the bitwise-OR operator in C. 


You will see the bitwise-OR operator a lot in Cocoa and iOS programming.
You can use bitwise-OR together the constants that represent the particular aspects you want.


NSError *e;
NSDataDetector *d = [NSDataDetector dataDetectorWithTypes:
                                             NSTextCheckingTypePhoneNumber | NSTextCheckingTypeDate
                                             error:&e];


  • In objective-C we use bitwise-AND (&) to see if a certain bit, or flag is on

if ([currentDetector checkingTypes] & NSTextCheckingTypePhoneNumber){
    NSLog (@"This one is looking for phone numbers");
}



  • ^ exclusive OR (XOR) - two bytes together to create a third (beware is not exponentiation operator=pow())
  • complement is the byt that is the exact opposite of another (reverse all the 0 to 1 and all the 1 becomes 0).
  • A<<2. << Left-shift. Every time you left -shift a number one place, you double tis value.
  • A>>1. >>Right-shift. Every time you right-shift a number one place, you half its value (if it is odd round down).

An elegant way to declare the bit-masks with enum
enum {
 UIDataDetectorTypePhoneNumber = 1 << 0,
 UIDataDetectorTypeLink                = 1 << 1,
 UIDataDetectorTyprAddress           = 1 << 2,
 UIDataDetectorTypeNone               =0,
 UIDataDetectorTypeAll                   = NSUIntegerMax
};




examples from The big Nerd Ranch Guide - Objective C 

Challenge page 235 The Big Nerd Ranch Guide - Objective C

pass the block anonymously as an argument to enumerateOBjectsUsingblock: 


[oldStrings enumerateObjectsUsingBlock:^(id string, NSUInteger i, BOOL *stop) {
            NSRange yRange = [string rangeOfString:@"y"
                                           options:NSCaseInsensitiveSearch];
            //Did I find a y?
            if (yRange.location != NSNotFound) {
                *stop = YES;    //Prevent further iterations
                return;         //Stop this iteration
            }
            NSMutableString *newString = [NSMutableString stringWithString:string];
            //Iterate over the array of vowels, replacing occurrences of each
            //with an empty string
            for (NSString *s in vowels) {
                NSRange fullRange = NSMakeRange(0, [newString length]);
                [newString replaceOccurrencesOfString:s
                                           withString:@""
                                              options:NSCaseInsensitiveSearch
                                                range:fullRange];
            }
            [newStrings addObject:newString];
        }];


add a notification update with block 

[[NSNotificationCenter defaultCenter] addObserverForNameNSSystemTimeZoneDidChangeNotification 
                                                          object:nil 
                                                           queue:nil
                                                      usingBlock: ^(NSNotification *note){
                                                          NSLog (@"The system time zone has changed!");    
                                                      }];

Blocks

^(double div, double divisor) {
  double quotient = div / divisor;
  return quotient;
};

^: identifies a block

Block can take arguments

If you want to access a block by a name, we have to assign it to a block variable.

void (^devow) (id, NSUInteger, BOOL *)
Block variable declaration


notice that the block assignment ends with a semi-colon just like any variable assignment would.

You can use typedef to declare a block at the start of top of the file like
typedef void (^ArrayEnumerationBlock) (id, NSUInteger, BOOL *);

Rather to write: void (^devowelizer) (id, NSUINteger, BOOL *);
you can   write: ArrayEnumerationBlock devowelizer;

If a block returns a value you can call that block variable like a function

double (^divinationBlock) (double, double) = ^(double k, double j) {
            return k/j;
}

Blocks are created and stored on the stack and will be destroyed (with the stack) when the function or method that created the block returns. To copy a block from the stack to the heap, you send it the copy message:
ArrayEnumerationBlock iVarSomething = [something copy]; (now the new block variable is a pointer to the block). Methods that takes blocks as arguments, are expected to copy blocks passed to them.
A heap-based block behaving like an object comes with some memory management issues:

#Source: The Big Nerd Ranch Guide (Objective C) - kindle version


  • external variables are captured by the block when the copy is made.
  • to avoid retain cycles declare a __weak pointer outside the block
  • variables captured by a block are constant within the block and you cannot change their values (you can still send the object messages that can change its contents, you cannot modify the pointer itself).
  • if you want to change them you need to use __block otherwise you get compilation error.
__block int counter =0 ;
void (^counterBlock) () = ^ {counter++;};
...
counterBlock (); //Increments counter to 1
counterBlock ();//Increments counter to 2





Σάββατο, 7 Απριλίου 2012

Categories

An easy way to add methods to any existing class.

#import "ClassName.h"
@interface ClassName ( CategoryName )
// method declarations
@end

From Documentation:
How You Can Use Categories
There are several ways in which you can use categories:
  • To extend classes defined by other implementorsFor example, you can add methods to the classes defined in the Cocoa frameworks. The added methods are inherited by subclasses and are indistinguishable at runtime from the original methods of the class. 
  • As an alternative to a subclassRather than define a subclass to extend an existing class, through a category you can add methods to the class directly. For example, you could add categories to NSArray and other Cocoa classes. As in the case of a subclass, you don’t need source code for the class you’re extending.
  • To distribute the implementation of a new class into multiple source files For example, you could group the methods of a large class into several categories and put each category in its own file. When used like this, categories can benefit the development process in a number of ways—they:
    • Provide a simple way of grouping related methods. Similar methods defined in different classes can be kept together in the same source file.
    • Simplify the management of a large class when several developers contribute to the class definition.
    • Let you achieve some of the benefits of incremental compilation for a very large class.
    • Can help improve locality of reference for commonly used methods.
    • Enable you to configure a class differently for separate applications, without having to maintain different versions of the same source code.
  • To declare informal protocols See “Informal Protocols ,” as discussed under “Declaring Interfaces for Others to Implement.”
Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:
  • When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.
  • A category cannot reliably override methods declared in another category of the same class.This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.
  • The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.

Παρασκευή, 6 Απριλίου 2012

What Is Key-Value Coding?


What Is Key-Value Coding?

Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables. In essence, key-value coding defines the patterns and method signatures that your application’s accessor methods implement.
Accessor methods, as the name suggests, provide access to your application’s data model’s property values. There are two basic forms of accessor—get accessors and set accessors. Get accessors, also referred to as getters, return the values of a property. Set accessors, also referred to as setters, set the value of a property. There are getter and setter variants for dealing with both object attributes and to-many relationships.
Implementing key-value coding compliant accessors in your application is an important design principle. Accessors help to enforce proper data encapsulation, isolatememory management to centralized locations, and facilitate integration with other technologies such as key-value observing, Core Data, Cocoa bindings, and scriptability. Key-value coding methods can, in many cases, also be utilized to simplify your application’s code. See Model Object Implementation Guide for more guidance on why your application should implement key-value coding compliant accessors and make use of them.
The essential methods for key-value coding are declared in the NSKeyValueCoding Objective-C informal protocol and default implementations are provided by NSObject.
Key-value coding supports properties with object values, as well as the scalar types and structs. Non-object parameters and return types are detected and automatically wrapped, and unwrapped, as described in “Scalar and Structure Support.”

examples:
Object types:
[a setProductName:@"Washing Machine"]
[a setValue:@"Washing Machine" forKey:@"productName"];

[a valueForKey:@"productName"]

Non-object types
[a setVoltage:240];
[a setValue:[NSNumber numberWithInt:240] forKey:@"voltage"];

some notes from The Big Nerd Ranch Guide:
Note that even though you have no accessor methods for one object, the variable can still be set and read from others methods (via key-value coding). This is an obvious violation of the idea of object encapsulation - methods of an object are public, but the instance variables are delicate and should be kept private. If key-value coding weren't astonishingly useful, no one would tolerate it.

Charbonneau is correct. I get an XML feed in which corresponds to an object on the iPhone/Mac client. Typically it'll be something like <user><name>Bob</name><age>43</age></user> I had a method before that would key/value code NSDictionary instances. – Coocoo4Cocoa Dec 18 '08 at 20:53

Πέμπτη, 5 Απριλίου 2012

The Designated Initializer

From the Documentation:

The designated initializer is the method in each class that guarantees inherited instance variables are initialized (by sending a message to super to perform an inherited method). It’s also the method that does most of the work, and the one that other initialization methods in the same class invoke. It’s a Cocoa convention that the designated initializer is always the method that allows the most freedom to determine the character of a new instance (usually this is the one with the most parameters, but not always).

  • It’s important to know the designated initializer when defining a subclass
  • General principle: The designated initializer in a class must, through a message to super, invoke the designated initializer in a superclass.
From the Big Nerd Ranch Guide:
"A class has only one designated initializer method. If the class has other initializers, then the implementation of those initializers must call (directly or indirectly) the designated initializer. 
  • Thus, the designated initializer acts as a funnel-point.
  • When you create a class whose designated initializer has a different name than its superclass's designated initializer (as you did in Appliance and OwnedAppliance), you have a responsibility to document that in the header file. 
  • If a class has several initializers, only one should do the real work. That method is known as the designated initializer. All other initializers should call, either directly or indirectly, the designated initializer. 
  • The designated initializer will call the superclass's designated initializer before initializing its instance variables
  • If the designated initializer of your class has a different name than the designated initializer of its superclass, you must override the superclass's designated initializer so that it calls the new designated initializer.
  • if you have several initializers, clearly document which is the designated initializer in the header. 


Wy shouldn't I use accessor methodes in an init method?

First: Apples Documentation says so...

Don’t Use Accessor Methods in Initializer Methods and dealloc
The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc. To initialize a counter object with a number object representing zero, you might implement an init method as follows:
- init {

    self = [super init];

    if (self) {

        _count = [[NSNumber alloc] initWithInteger:0];

    }

    return self;

}

To allow a counter to be initialized with a count other than zero, you might implement an initWithCount: method as follows:
- initWithCount:(NSNumber *)startingCount {

    self = [super init];

    if (self) {

        _count = [startingCount copy];

    }

    return self;

}

Since the Counter class has an object instance variable, you must also implement a dealloc method. It should relinquish ownership of any instance variables by sending them a release message, and ultimately it should invoke super’s implementation:
- (void)dealloc {

    [_count release];

    [super dealloc];

}



What stackoverflow says? 

  • It's basically a guideline to minimize the potential for bugs.
  • It is all about using idiomatically consistent code. If you pattern all of your code appropriately there are sets of rules that guarantee that using an accessor in init/dealloc is safe.





What Big Nerd Ranch guide says?
"..In most cases, there is a little reason to do one over the other, but it makes for a great argument. The argument goes like this: The assign guy says, "You can't use an accessor method in an init method! The accessor asumes that the object is ready for work, and it isn't ready for work until after the init method is complete." Then the accessor method guy says, "Oh, come on. In the real world that is almost never an issue. My accessor method might be taking care of other stuff for me. I use my accessor anytime I set that variable." In reality, either approach will work in the cast majority of cases. 

Τρίτη, 3 Απριλίου 2012

What is the purpose of using IBAction and IBOutlet in Objective-C coding for the iPhone, does it make any difference if I don't use them?


As "The Big Nerd Ranch Guide" refers
"When you entered the IBOutlet and IBAction keywords, you were flaggin those outlets and actions for Interface Builder, saying "Hei! when I try to connect a pointer in IB, make sure and put this item in the list of available connections!" As you write your code, Interface Builder scans for IBOutlet and IBAction keywords so that it knows what connections you might want to make.

Here are the actual definitions: 
#define IBAction void
#define IBOutlet
So the IBAction is replaced with void before the compiler sees it and that IBOutlet disappears (see what #define does). 

Thus, at compile time,
  • all IBOutlet keywords are removed entirely 
  • all IBAction keywords are replaced by void because actions invoked by user interface controls are not expected to have a return value. 

Here is the Documentation link:

Interface Builder Constants

Type qualifiers used by Interface Builder to synchronize with Xcode.
#define IBAction void
#define IBOutlet
#define IBOutletCollection(ClassName)
Constants
IBAction
Type qualifier used by Interface Builder to synchronize actions. Use this type as the return type of any action methods defined in your project. For examples of how to use this identifier, see “Xcode Integration”.
Available in iOS 2.0 and later.
Declared in UINibDeclarations.h.
IBOutlet
Identifier used to identify a property so Interface Builder can synchronize the display and connection of outlets with Xcode. Insert this identifier immediately before the type in any declarations. For examples, including how to use it with the @property syntax, see “Xcode Integration”.
Available in iOS 2.0 and later.
Declared in UINibDeclarations.h.
IBOutletCollection
Identifier used to qualify a one-to-many instance-variable declaration so that Interface Builder can synchronize the display and connection of outlets with Xcode. You can insert this macro only in front of variables typed as NSArray or NSMutableArray.
This macro takes an optional ClassName parameter. If specified, Interface Builder requires all objects added to the array to be instances of that class. For example, to define a property that stores only UIViewobjects, you could use a declaration similar to the following:
@property (nonatomic, retain) IBOutletCollection(UIView) NSArray *views;
For additional examples of how to declare outlets, including how to create outlets with the @propertysyntax, see “Xcode Integration”.
Available in iOS 4.0 and later.
Declared in UINibDeclarations.h.
Discussion
For more information about how to use these constants, see “Communicating with Objects”. For in


Here is a similar answer from stackoverflow

IBAction and IBOutlet are macros defined to denote variables and methods that can be referred to in Interface Builder.
IBAction resolves to "void" and IBOutlet resolves to nothing, but they signify to Xcode and Interface builder that these variables and methods can be used in Interface builder to link UI elements to your code.
If you're not going to be used Interface Builder at all, then you don't need them in your code, but if you are going to use it, then you need to specify IBAction for methods that will be used in IB and IBOutlet for objects that will be used in IB.
link|edit

How to get the attributes of an instance of NSTableView


The table view object (in MacOSx) is a collection of nested objects :

  • NSScrollView, 
  • NSTableView,
  • NSTableColumn
To get to a ojbect in this collection, 
  • hold down the Control and Shift keys, while clicking on the table view. 
You will see a list of the objects under the cursor, and you can select the object you're interested in. 


Apple human interface guidelines or HIG

I need to make some notes on that (Apple Human Interface guidelines or HIG)

soon the summary will pop up :)

last update 3/4/2012