Extension of iOS-Objective-C and Java. Dive into iOS Foundation and Attribute Strings.
Creating Objects
create objects with alloc and init
1
NSMutableArray *cards = [[NSMutableArray alloc] init]; CardMatchingGame *game = [[CardMatchingGame alloc] initWithCardCount:12 usingDeck:d];
create with class methods
1
NSString’s + (id)stringWithFormat:(NSString *)format, ... NSString *moltuae = [NSString stringWithFormat:@“%d”, 42];
Sometimes both a class creator method and init method exist
1
[NSString stringWithFormat:...] same as [[NSString alloc] initWithFormat:...]
iOS seems to be moving more toward the alloc/init versions with new API, but is mostly neutral.
ask other objects to create new objects
1
2
3NSString’s - (NSString *)stringByAppendingString:(NSString *)otherString;
NSArray’s - (NSString *)componentsJoinedByString:(NSString *)separator;
NSString’s & NSArray’s - (id)mutableCopy;But not all objects given out by other objects are newly created,
NSArray’s - (id)lastObject; NSArray’s - (id)objectAtIndex:(int)index;
unless the method has the word “copy” in it, if the object already exists, you get a pointer to it. If the object does not already exist (like the first 2 examples at the top), then you’re creating.
Dynamic Binding
Objective-C has an important type called id.
It means “pointer to an object of unknown/unspecified” type. id myObject;
Really all object pointers (e.g. NSString *) are treated like id at runtime. But at compile time, if you type something NSString * instead of id, the compiler can help you. It can find bugs and suggest what methods would be appropriate to send to it, etc.
If you type something using id, the compiler can’t help very much because it doesn’t know much. Figuring out the code to execute when a message is sent at runtime is called “dynamic binding.”
static typing
1
NSString *s = @“x”; // "statically" typed
id obj = s; // legal, Never use “id *” by the way
NSArray *a = obj; // also legal but dangerous
When to use intentionally
- When we want to mix objects of different classes in a collection (e.g. in an NSArray).
- When we want to support the “blind, structured” communication in MVC (i.e. delegation). And there are other generic or blind communication needs.
- But to make these things safer, we’re going to use two things: Introspection and Protocols.
Introspection
Asking at runtime what class an object is or what messages can be sent to it.
All objects that inherit from NSObject know these methods:
1 | isKindOfClass: returns whether an object is that kind of class (inheritance included) |
Protocol
A syntax that is “in between” id and static typing.
Does not specify the class of an object pointed to, but does specify what methods it implements. Example …
1 | id <UIScrollViewDelegate> scrollViewDelegate; |
A little bit like template in C++ and Java.
Arguments to these methods
- Class testing methods take a Class
1 | if ([obj isKindOfClass:[NSString class]]) { NSString *s = [(NSString *)objstringByAppendingString:@”xyzzy”]; } |
Method testing methods take a selector (SEL)
1 | // Special @selector() directive turns the name of a method into a selector |
ask an object to perform SEL
1 | // Using the performSelector: or performSelector:withObject: methods in NSObject |
NSObject
Base class for pretty much every object in the iOS SDK.
- (NSString *)description
is a useful method to override (it’s %@ in NSLog()). Example … NSLog(@“array contents are %@”, myArray);
The %@
is replaced with the results of invoking [myArray description].
Copying objects. This is an important concept to understand (why mutable vs. immutable?).
- (id)copy; // not all objects implement mechanism (raises exception if not)
- (id)mutableCopy; // not all objects implement mechanism (raises exception if not)
1
2
3
4
5
6
7
8
9
10
11
12
13
## NSArray
Ordered collection of objects.
Immutable. That’s right, once you create the array, you cannot add or remove objects.
All objects in the array are held onto strongly. Usually created by manipulating other arrays or with `@[]`.
```
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index; // crashes if index is out of bounds; returns id!
- (id)lastObject; // returns nil (doesn’t crash) if there are no objects in the array
- (id)firstObject; // returns nil (doesn’t crash) if there are no objects in the array
- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject: (id)selectorArgument;
- (NSString *)componentsJoinedByString:(NSString *)separator;
```
## NSMutableArray
Mutable version of NSArray.
Create with alloc/init or ...
```
+ (id)arrayWithCapacity:(NSUInteger)numItems; // numItems is a performance hint only
+ (id)array; // [NSMutableArray array] is just like [[NSMutableArray alloc] init]
NSMutableArray inherits all of NSArray’s methods.
Not just count, objectAtIndex:, etc., but also the more interesting ones mentioned above.
Other key methods:
1
- (void)addObject:(id)object; // to the end of the array (note id is the type!) - (void)insertObject:(id)object atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;
## Enumeration
- Looping through members of an array in an efficient manner
1
Example: NSArray of id NSArray *myArray = ...; for (id obj in myArray) {
// do something with obj, but make sure you don’t send it a message it does not respond to if ([obj isKindOfClass:[NSString class]]) {
// send NSString messages to obj with no worries }
}
## Foundation Framework
### NSNumber
Object wrapper around primitive types like int, float, double, BOOL, enums, etc.
1
NSNumber *n = [NSNumber numberWithInt:36];
float f = [n floatValue]; // would return 36.0 as a float (i.e. will convert types)
// Useful when you want to put these primitive types in a collection (e.g. NSArray or NSDictionary).
NSNumber *three = @3;
NSNumber *underline = @(NSUnderlineStyleSingle); // enum
NSNumber *match = @([card match:@[otherCard]]); // expression that returns a primitive type
1 |
|
NSValue *edgeInsetsObject = [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(1,1,1,1)]
1 |
|
- (NSDictionary *)attributesAtIndex:(NSUInteger)index
effectiveRange:(NSRangePointer)range;1
2
3
4
5
### NSMutableAttributedString
- add an attribute to a range of characters - (void)addAttributes:(NSDictionary *)attributes range:(NSRange)range;
// which will change the values of attributes in attributes and not touch other attributes. Or you can set the attributes in a range - (void)setAttributes:(NSDictionary *)attributes range:(NSRange)range;
// which will remove all other attributes in that range in favor of the passed attributes. You can also remove a specific attribute from a range - (void)removeAttribute:(NSString *)attributeName range:(NSRange)range;@{ NSFontAttributeName :
1
2
3
4
5
6
7
- Modifying the contents of the string (changing the characters)
do that with methods to append, insert, delete or replace characters. Or call the `NSMutableAttributedString` method `- (NSMutableString *)` mutableString and modify the returned NSMutableString (attributes will, **incredibly, be preserved**!)
### a set of attributes
[UIFont preferredFontWithTextStyle:UIFontTextStyleHeadline]
NSForegroundColorAttributeName : [UIColor greenColor],
NSStrokeWidthAttributeName : @-5,
NSStrokeColorAttributeName : [UIColor redColor] }
```
Reference
Online Course: Developing iOS7 Apps for iPhone and iPad, Stanford