chapter1 The Basic

1.Object-c do not support multple inheritance. objects that inherit from NSObject directly or indirectly can take advantage of Object-C's distinctive memory managment tool.

2.Xcode various build type:

 Build for Running  (debug on simulator or on a device)
Build for Testing (run unit test that you written for you apps, Unit test ,in short are a set of instructions that you provide to Xcode,Xcode will run these instructions before make the final build)

Build for Profiling (test the performance for you app, Profiling is the process by which you can find bottlenecks ,memory leaks and other quality-related issues)

Build for Archiving (build for distribute)

To compile you apps in Xcode, simply select the Product menu item,choose Build For.......


3.commonly use  data type: NSInteger, NSUInteger, float, NSString,NSArray,NSSet. etc.

NSString  , , NSMutableString

Objective-C strings should be placed inside double quotes. The starting double-quote  should be prefixed with an at sign (@). For instance, the sentence Hello, World, represented   as a string in Objective-C, is written like so:
@"Hello, World"


NSString *simpleString = @"This is a simple string";


NSString *anotherString =[NSString stringWithString:@"This is another simple string"];


NSString *oneMorestring =[[NSString alloc] initWithString:@"One more!"];


NSMutableString *mutableOne =[NSMutableString stringWithString:@"Mutable String"];


NSMutableString *anotherMutableOne =[[NSMutableString alloc] initWithString:@"A retained one"];


NSMutableString *thirdMutableOne =[NSMutableString stringWithString:simpleString];


NSString *simpleString = @"123.456";
NSInteger integerOfString = [simpleString integerValue];
NSLog(@"integerOfString = %ld", (long)integerOfString);


CGFloat floatOfString = [simpleString floatValue];
NSLog(@"floatOfString = %f", floatOfString);
double doubleOfString = [simpleString doubleValue];
NSLog(@"doubleOfString = %f", doubleOfString);


The output of this code is:
integerOfString = 123
floatOfString = 123.456001
doubleOfString = 123.456000


If you would like to work with C Strings, you can! You will use them like NSString  without the leading at sign, like so:
char *cString = "This is a C String";
If you want to convert an NSString to a C String, you must use the UTF8String method  of NSString, like so:
const char *cString = [@"Objective-C String" UTF8String];
NSLog(@"cString = %s", cString);


find a string inside another string, rangeOfString: method of NSString. The return value of this method is of type NSRange:
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;


NSString *haystack = @"My Simple String";
NSString *needle = @"Simple";
NSRange range = [haystack rangeOfString:needle];
if (range.location == NSNotFound){
/* Could NOT find needle in haystack */
} else {
/* Found the needle in the haystack */
NSLog(@"Found %@ in %@ at location %lu",needle,haystack,(unsigned long)range.location);
}

In the Platform Dependencies section of the String Programming Guide published by Apple, it’s been explained why we need to typecast integral
values with specifiers such as unsigned long.


rangeOfString:options:

enum {
NSCaseInsensitiveSearch = 1,
NSLiteralSearch = 2,
NSBackwardsSearch = 4,
NSAnchoredSearch = 8,
NSNumericSearch = 64,
NSDiacriticInsensitiveSearch = 128,
NSWidthInsensitiveSearch = 256,
NSForcedOrderingSearch = 512,
NSRegularExpressionSearch = 1024

};
typedef NSUInteger NSStringCompareOptions;
As you can see, the values in this enumeration are multiples of 2. That indicates that  you can mix them with the logical OR operator (the | pipe character)

NSString *haystack = @"My Simple String";
NSString *needle = @"simple";
NSRange range = [haystack rangeOfString:needle  options:NSCaseInsensitiveSearch];
if (range.location == NSNotFound){
/* Could NOT find needle in haystack */
} else {
/* Found the needle in the haystack */
NSLog(@"Found %@ in %@ at location %lu",needle,haystack,(unsigned long)range.location);
}


NSMutableString *mutableString =[[NSMutableString alloc] initWithString:@"My MacBook"];
/* Add string to the end of this string */
[mutableString appendString:@" Pro"];
/* Remove the "My " string from the string */
[mutableString  replaceOccurrencesOfString:@"My "  withString:[NSString string]   options:NSCaseInsensitiveSearch /* Case-insensitive */
range:NSMakeRange(0, [mutableString length])];

 

If you are comparing objects, it is best to use the isEqual: instance method of the  NSObject class:
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = object1;
if ([object1 isEqual:object2]){
NSLog(@"Both objects are equal.");
} else {
NSLog(@"Objects are not equal.");
}

isEqual 比较的是地址,,,

Some objects such as strings, however, have their own comparison methods, changing  the way we compare two strings. For instance, you can have two string objects that  contain the same characters. If you compare them using their isEqual: instance method,you will get the result NO, because they are different objects


char *myString = "This is my string";
NSUInteger counter = 0;
for (counter = 0;  counter < strlen(myString); counter++)

{

char character = myString[counter];
NSLog(@"%c", character);
}

if counter  define in the for header, then outside the for loop, this variable are not visible any more


while loop

char *myString = "Some Random String";
NSUInteger counter = 0;
char character;

while ((character = myString[counter++]) != 'R' &&
counter < strlen(myString)){
/* Empty */
}
NSLog(@"Found the letter R at character #%lu", (unsigned long)counter+1);


char *cString = "My String";
char *stringPointer = cString;
while (*stringPointer != 0x00)

{
NSLog(@"%c", *stringPointer);
stringPointer++;
}


good style:

-(BOOL) sendEmailTo:(NSString *)paramTo withSubject:(NSString *)paramSubject andEmailMessage:(NSString *)paramEmailMessage

{
/* Send the email and return an appropriate value */
if ([paramTo length] == 0 ||
[paramSubject length] == 0 ||
[paramEmailMessage length] == 0){
/* One or some of the parameters are empty */
NSLog(@"Empty parameter(s) is/are provided.");
return NO;
}
return YES;
}

[self sendEmailTo:@"someone@somewhere.com"
withSubject:@"My Subject"
andEmailMessage:@"Please read my email."];

//although is no compile error, but bad style

- (BOOL) sendEmailTo:(NSString *)paramTo :(NSString *)paramSubject :(NSString *)paramEmailMessage

{
/* Send the email and return an appropriate value */
if (paramTo length] == 0 ||
[paramSubject length] == 0 ||
[paramEmailMessage length] == 0){
NSLog(@"Empty parameter(s) is/are provided.");
return NO;
}
return YES;
}

[self sendEmailTo:@"someone@somewhere.com"
:@"My Subject"
:@"Please read my email."];

define message in Object-c
1. Type − if you want an instance method or + if you want a class method.
2. Choose the return type of your method and enclose it within parentheses—for
instance, (void) for no return value, (BOOL) for a Boolean value, (NSObject *) to
return an instance of NSObject, and so on.   (注意对象要返回 pointer)
3. Choose a name for your method. Start the name with a lowercase letter. It is common
in Objective-C to start method names with a lowercase letter—for instance,
sendEmailTo instead of SendEmailTo.
4. If you do not want any parameters for your method, jump to step 9.
5. Choose two names for your parameter.  first name is mandatory, the second is optional.

剩下的步骤我们只要注意用: 分割开各个parameter 就是了,,,


You would like to implement two or more methods with the same name in one object.
In object-oriented programming, this is called method overloading. However, in Objective-
C, method overloading does not exist in the same way as it does in other programming
languages such as C++.

- (void) drawRectangle

{
[self drawRectangleInRect:CGRectMake(0.0f, 0.0f, 4.0f, 4.0f)];
}
- (void) drawRectangleInRect:(CGRect)paramInRect

{
[self drawRectangleInRect:paramInRect  withColor:[UIColor blueColor]];
}
- (void) drawRectangleInRect:(CGRect)paramInRect   withColor:(UIColor*)paramColor

{
[self drawRectangleInRect:paramInRect  withColor:paramColor  andFilled:YES];
}

This example shows a typical pattern in overloading.

in C++, to overload a method, the programmer needs to assign a different number of parameters
to the same method and/or change a parameter’s data type.
In Objective-C, however, you simply change the name of at least one parameter.
Changing the type of parameters will not work:
- (void) method1:(NSInteger)param1{
/* We have one parameter only */
}
- (void) method1:(NSString *)param1{
/* This will not compile as we already have a
method called [method1] with one parameter  改参数类型不算overload, will hit error */

}
Changing the return value of these methods will not work either:
- (int) method1:(NSInteger)param1{
/* We have one parameter only */
return param1;
}
- (NSString *) method1:(NSString *)param1{
/* This will not compile as we already have a  method called [method1] with one parameter

改返回类型也不算*/
return param1;
}

As a result, you need to change the number of parameters or the name of (at least) one
parameter that each method accepts. 
- (NSInteger) method1:(NSInteger)param1{
return param1;

}

- (NSString*) method1:(NSString *)param1  andParam2:(NSString *)param2

{
}

or change the parameter name:

- (void) drawCircleWithCenter:(CGPoint)paramCenter
radius:(CGFloat)paramRadius{
/* Draw the circle here */
}
- (void) drawCircleWithCenter:(CGPoint)paramCenter
Radius:(CGFloat)paramRadius{
/* Draw the circle here */
}


 Allocating and Initializing Objects

You must both allocate and initialize an object before using it. An object can be allocated  using the alloc instance method.This class method will allocate memory to hold  the object and its instance variables and methods. However, allocation leaves memory  undefined. So in addition, each object must be initialized, which sets the values of its  data.One initialization method must be the designated initializer, which is normally  the initialization method with the most parameters. For instance, the initWithFrame:   (注意: 冒号也是message 的一部分) method is the designated initializer of objects of type UIView. Always allocate and initialize  your objects, in that order, before using them.

When implementing a new object, do not override the alloc method. This method is  declared in NSObject. Instead, override the init method and create custom initialization methods that handle required parameters for the specific object you are working on.

MyObject *someObject = [[MyObject alloc] init];
/* Do something with the object, call some methods, etc. */
[someObject doSomething];


MyObject *someObject = [MyObject alloc];   // not call the ini method
/* Do something with the object, call some methods, etc. */
[someObject doSomething];   // 就算没init 也没错误,那不是跟用前需要先alloc then init 的princile 不match?

We thought we had to initialize the object before we could use it.
Perhaps Apple can explain this behavior better:
An object isn’t ready to be used until it has been initialized. The init method defined in
the NSObject class does no initialization; it simply returns self.  //这么说其实不是不能用,,I think use untile initalized, is consider from business perspective view. from programe view, no error in runtime.

Please bear in mind that the
return value for initializer methods of an object is of type id, so the initializer method  might even return an object that is not the same object that the alloc method returned  to you. This technique is called two-stage creation and is extremely handy.

 

1.16 Adding Properties to Classes

can take advantage of dot notation  to access those values, as opposed to using methods on your classes.

using the @property keyword in header file. and in the implement file,you need to synthesize it.

.h

@property (nonatomic, strong) NSString *firstName;

.m

@synthesize firstName = _firstName

                     第一个是property name, the sencode is the instance variable name. 通过-> 可以访问到 _firstName

In an older version of the Objective-C runtime, for @property to work, we also had to define an instance variable. An instance variable is a variable   whose memory management is done by the programmer herself.
Instance variables are also not exposed to classes outside the scope of  the class that defines them (i.e., they are not exposed to any class that  simply imports the class with the instance variable). Instance variables
are normally called ivars by professional Objective-C developers (ivar is pronounced I-WAR).也就是instance variable is  proteced accessible control.

With the new runtime, we don’t have to define ivars anymore. We simply  define the property and the LLVM compiler defines the ivar for us. (也就是说LLVM 通过synthesize  可以帮我们合成 _firstName instance variable)  If you are using the GCC compiler, which is rather unlikely, you will see  big differences from how the LLVM compiler treats ivars. For instance,in GCC 4.2, an ivar is not accessible to any subclass of a class, whereas
if you are using LLVM Compiler, a subclass of a class can use its superclass’s  ivars.So make sure you are using Apple’s latest compiler, which   is LLVM.


If you want to define a read-only property, all you have to do is to define your property  using the @readonly keyword, like so:
@property (nonatomic, strong, readonly) NSString *lastName;




1.17 Moving from Manual Reference Counting to Automatic
Reference Counting

new storage attributes introduced with the latest LLVM compiler: strong, weak, and unsafe_unretained.

(当然还有copy and assign)


strong
An object of this type is automatically retained at runtime and will be valid until
the end of its scope, where it will automatically be released. For those familiar with
Objective-C’s traditional way of memory management, this keyword is similar to
the retain keyword.  (也就是说 [oneObject firstName:anotherObj] 我会retain 住anotherObj, 哪怕anotherObj 被其他人release 了,你还是有效的,当我要完了,你也跟着完了,除非有其他人也象我一样retain 住你)

weak
This is zeroing weak referencing. If a variable is defined with this keyword, when  the object to which this variable points gets deallocated, this value will get set to  nil. For instance, if you have a strong string property and a weak string property  and set the weak property’s value to the strong property’s value, when the strong  property gets deallocated, the weak property’s value will get set to nil.

(也就是说 [oneObject firstName:anotherObj] 我 没retain 住anotherObj,如果anotherObj 被其他人release 到完了,,firstName 会被设置成nil,这样至少不会遇到dangling pointer issue, because can send messge to nil)



unsafe_unretained
This is simply pointing one variable to another. This will not retain the object into
the new variable, it will simply assign the object to the variable.

(也就是说 [oneObject firstName:anotherObj] 我 没retain 住anotherObj,如果anotherObj 被其他人release 到完了,,firstName 不会被设置成nil,此时如果调用这个anotherObj,  我完了,will crash)


By default, all local variables are strong variables. In contrast, properties must explicitly  specify their storage attribute.

 __strong, __weak, and __unsafe_unretained specifiers for local variable

Here is an example:


{

__strong NSString *yourString = @"Your String";  //default is __strong  ,注意收字母不用大写
__weak NSString *myString = yourString;
yourString = nil;  //release yourString,, 而不用[yourString release] , the same effect, 此时myString 其实没有被设置成nil 的,,因为方法还没完ARC ,没来的及起作用
__unsafe_unretained NSString *theirString = myString;

}

__autoreleasing specifier , 是由调用者负责alloc,, 释放由auto release pool 负责

- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError{
NSArray *objects = [[NSArray alloc] initWithObjects:@"A simple error", nil];
NSArray *keys =
[[NSArray alloc] initWithObjects:NSLocalizedDescriptionKey, nil];
NSDictionary *errorDictionary = [[NSDictionary alloc] initWithObjects:objects
forKeys:keys];

//这里我只是alloc 了*paramError,释放不由我负责

*paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1  userInfo:errorDictionary]; 
}

- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSError *error = nil;
[self generateErrorInVariable:&error];  // &error, 指针的指针,,,,
NSLog(@"Error = %@", error);
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}

In this example, the application:didFinishLaunchingWithOptions: method didn’t allocate  the instance of NSError; the generateErrorInVariable method did. But for the  compiler to understand the scope of the error object, the generateErrorInVariable method mentioned to the compiler that the object which will be created into its error
parameter needs to be automatically released if it is no longer needed.


1.18 Typecasting with Automatic Reference Counting

Use the __bridge, __bridge_transfer, and __bridge_retained typecasting specifiers.when working with Core Foundation objects   inside your Objective-C code.

Core Foundation Object 不是Object C 写的,所以ARC 不会作用到CF Object,CF Object 其实是C 写的一个对象库,

那他也需要对象的memory 管理。 CFRetain(),CFRelease() , 但当Object C  Object  and CF Object 互相typecasting 的时候,如果我们help compiler ,it will hit compiler error. , now __bridge , __bridge_transfr, and __bridge_retained, for this purpose.

(首先我们要注意typecasting 并没用创建新的对象,只是以不同的类型来引用这个对象了,,)

__bridge
Simply typecasts the object on the right side of the equation to the left side. This
will not modify the retain count on any of the objects; neither the one on the left
nor the one on the right side of the equation.  (retain cout 不变)

__bridge_transfer
This typecast will assign the object on the right side to the object on the left and
will release the object on the right side. So if you have a Core Foundation string,
like the one we saw before, that you have just created and want to place it inside
a local variable of type NSString (local variables are by default strong), then you

should use this typecasting option because then you won’t  have to release the

Core Foundation string after the assignment. 

(retain cout 相当于 transfer 到左边,右边release)


__bridge_retained
This is similar to the __bridge_transfer typecast, but will retain the object on the
right side of the equation as well. , so you need to call CFRelease later.


{

CFStringRef coreFoundationString =CFStringCreateWithCString(CFAllocatorGetDefault(),
"C String",kCFStringEncodingUTF8);

NSString *objCString = (__bridge_transfer NSString *)coreFoundationString; // coreFoundationString will be auto call CFRealse() after assigment so no need to call again.
NSLog(@"String = %@", objCString);

}

{

CFStringRef coreFoundationString =
CFStringCreateWithCString(CFAllocatorGetDefault(),"C String",kCFStringEncodingUTF8);
id unknownObjectType = (__bridge id)coreFoundationString; //id 当然是Object-C 的id,拉,是指针
CFStringRef anotherString = (__bridge_retained CFStringRef)unknownObjectType;// 再typecasting 回来后,coreFoundationString  又多了一次retain 了,so need to CFRealse,
NSString *objCString = (__bridge_transfer NSString *)coreFoundationString;
NSLog(@"String = %@", objCString);
objCString = nil; //其实不用也是可以的因为objCString 除了这个方法的scope ,ARC 就会起作用了
CFRelease(anotherString);

}


// 这种memory 的管理关键是我们要心里清楚,有多少retain, Creat 时候有 1,其他时候如果没retain 就不用release, retain and release 要对称出现。  , CF Object 的管好自己的平衡, Object-C 亦是如此, 两者在memory 管理上不公用一套机制。 so need to bear in mind this concept.



1.19 Delegating Tasks with Protocols

A protocol is the declaration (as opposed to implementation) of a set of methods and/
or properties  (properties also part of the  Protocol, 其实现是通过@synthesize 来合成 )in a header file (usually with the extension of .h).

Any object that you  declare to conform to such protocol is responsible for writing the implementation of
those methods and properties, depending on whether the protocol specifies them as
required or optional.
Think of protocols as sets of rules, with some rules being optional and others mandatory.
Any object saying that it conforms to that protocol must follow those rules.


#import <Foundation/Foundation.h>
@protocol PersonProtocol <NSObject>
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, unsafe_unretained) NSUInteger age;
@end


============

#import <Foundation/Foundation.h>
#import "PersonProtocol.h"
@interface Father : NSObject <PersonProtocol>  // <protocal name>
@end

As you can see, the compiler understands that the Father class wants to conform to the
PersonProtocol protocol. However, the Father class isn’t implementing the required
setter and getter methods of the properties defined in the PersonProtocol protocol. We
are seeing these warnings because anything defined in a protocol by default is required
from its conforming classes.


==============

#import <Foundation/Foundation.h>
@protocol PersonProtocol <NSObject>
@optional
@property (nonatomic, strong) NSString *firstName;

@required

@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, unsafe_unretained) NSUInteger age;
- (void) breathe;
@end

 

==================== perfect implementation==============

#import <Foundation/Foundation.h>
#import "PersonProtocol.h"
@interface Father : NSObject <PersonProtocol>  // <protocal name>
@end

-----.m file

#import Father.h

@implement Father

@synthesizelastName=_lastName,age=_age;

- (void) breathe

{


}

@end

Cocoa Touch has given protocols a really nice meaning in Objective-C. In Cocoa
Touch, protocols are the perfect means for defining delegate objects.


1.20 Determining Whether Instance or Class Methods Are
Available

instancesRespondToSelector:    // instance   -

respondsToSelector:                 //class          +

但这两个方法都是class method



- (BOOL) doesString:(NSString *)paramNeedle  existInString:(NSString *)paramHaystack;
The selector for this method would be [ doesString:existInString: ] //


There are two important concepts with regard to iOS SDK that you need to remember:
Base SDK
The SDK that you use to compile your application. This can be the latest and the
greatest SDK with access to all the new APIs available in iOS SDK.


Deployment SDK/Target
This is the SDK that will be used when you compile your app to run on devices.

(其实就是我们在选择deploy target 时候可以看到,选择ios5 ,etc....)


(测试的时候可能用了最latest ,比如Xcode4.5 其baseSDK 是ios7,但我deploy 的时候需要兼容其他的iso version, so I need to set the deploy sdk to iso5/6 , 这样iso7,6,5 都可以运行,当有的API 可能在就版本不存在,所以需要detect API exit or not)

印象中一次case, Xcode4.2 的project, import to Xcode 4.3, 报baseSDK not exit, 需要我们手动改Xcode4.3 的base SDK.  ,,也就是说有可能Xcode 不同版本其baseSDK 会不一样,我们无法改回以前的BaseSDK. need to use current base SDK of the current Xcode version

Example:

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:
@"Item 1",
@"Item 4",
@"Item 2",
@"Item 5",
@"Item 3", nil];
NSLog(@"Array = %@", array);
if ([NSArray instancesRespondToSelector:@selector(sortUsingComparator:)]){
/* Use the sortUsingComparator: instance method of the array to sort it */
}
else if ([NSArray instancesRespondToSelector:
@selector(sortUsingFunction:context:)]){
/* Use the sortUsingFunction:context: instance
method of the array to sort */
}
else {
/* Do something else */
}

/==========

NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:
@"Item 1",
@"Item 4",
@"Item 2",
@"Item 5",
@"Item 3", nil];
NSLog(@"Array = %@", array);
if ([array respondsToSelector:@selector(sortUsingComparator:)]){  // 用instace 对象去调,上一个example use NSArray class 对象去调

/* Use the sortUsingComparator: instance method of the array to sort it */
}
else if ([array respondsToSelector:@selector(sortUsingFunction:context:)]){
/* Use the sortUsingFunction:context: instance
method of the array to sort */
}
else {
/* Do something else */
}



============================

1.21 Determining Whether a Class Is Available at Runtime

if (NSClassFromString(@"NSJSONSerialization") != nil){
/* You can use this class */
[NSJSONSerialization JSONObjectWithData:... /* Put data here */
options:... /* Put options here */
error:...]; /* Handle errors here */
} else {
/* That class is not available */
}

1.22 Allocating and Making Use of Numbers

NSNumber object-oriented approach to handling numbers.

如果只是simple numbers (nonobjects), 使用如下:

NSInteger to hold signed (positive and negative) values,
NSUInteger to hold unsigned (only positive or zero) values,

CGFloat and double to  hold floating-point values

也就是非包装类型。

============

NSNumber *signedNumber = @-123456;    //@ 这是IOS6 的
NSNumber *unsignedNumber = @123456;
NSNumber *floatNumber = @123456.123456f;
NSNumber *doubleNumber = @123456.1234567890;


NSInteger signedValue = [signedNumber integerValue];
NSUInteger unsignedValue = [unsignedNumber unsignedIntegerValue];
CGFloat floatValue = [floatNumber floatValue];
double doubleValue = [doubleNumber doubleValue];
NSLog(@"signedValue = %ld, \n"\
"unsignedValue = %lu \n"\
"floatValue = %f \n"\
"doubleValue = %f",
(long)signedValue,
(unsigned long)unsignedValue,
floatValue,
doubleValue);

We are using the new features available in the LLVM compiler foriOS 6 SDK to create
our numbers. We can simply place our numbers straight after an at sign (@) and our
compiler will convert these numbers to instances of the NSNumber class. This technique
is called expression boxing. If you don’t want to use this feature, you can still use the
various methods of the NSNumber class to construct instances of this class.

//IOS5 以前的版本:

numberWithInteger:
Encapsulates an integer into an instance of NSNumber.

numberWithUnsignedInteger:
Encapsulates an unsigned integer (only positive or zero numbers) into an instance
of NSNumber.
numberWithFloat:
Encapsulates a floating-point value into an instance of NSNumber.
numberWithDouble:
Encapsulates a double value into an instance of NSNumber.

NSNumber *unsignedNumber = @123456;
/* Convert an unsigned integer inside an NSNumber to NSString */
NSString *stringValueOfNumber =
[NSString stringWithFormat:@"%lu",
(unsigned long)[unsignedNumber unsignedIntegerValue]];

 

NSNumber *unsignedNumber = @123456;
/* Convert an unsigned integer inside an NSNumber to NSString */
NSString *stringValueOfNumber =[NSString stringWithFormat:@"%lu",(unsigned long)[unsignedNumber unsignedIntegerValue]];


 
1.23 Allocating and Making Use of Arrays

You can place any object of type NSObject or any of its subclasses into
an array of type NSArray (or subclasses of that type). An array can contain
a mix of different types of objects. Not all objects have to be of the same
type. In other words, you can have one array with strings, numbers,
dictionaries, or even other arrays inside it. Arrays can contain any object
as long as those objects can be wrapped in the id data type wrapper.

也就是说只要id data type ,都可以放进NSArray, because id is exactly an pointer,  so primitive like NSInteger need to wrap into NSNumber.


NSArray *array = @[@"My String", @123, @-123];  //IOS6 later only

//iso5  and before

NSArray *array = [NSArray arrayWithObjects:stringObject,signedNumber,unsignedNumber, nil];


NSArray *array = @[@"My String", @123, @-123];
NSUInteger counter = 0;
for (counter = 0;
counter < [array count];
counter++){
id object = array[counter];
NSLog(@"Object = %@", object);
}

we can also use the
objectAtIndex: method to get an object at a specific index. Remember that indexes are
zero based. In other words, when the counter reaches -1, the loop has to stop because
there can be no negative indexes in an array.

fast enumeration to go through objects//:

for (id object in array){
NSLog(@"Object = %@", object);
}


//NSMutableArray example:

NSArray *anotherArray = @[@"String 1", @"String 2", @"String 3"];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:
@[@"My String", @123, @-123]];
[mutableArray addObject:@123];
[mutableArray removeObject:@-123];
[mutableArray addObjectsFromArray:anotherArray];
for (id object in mutableArray){
NSLog(@"Object = %@", object);
}

//using block object:

NSArray *myArray = @[
@"String 1",
@"String 2",
@"String 3",
@"String 4"];
[myArray enumerateObjectsUsingBlock:
^(__strong id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"Object = %@", obj);
}];

//sort a mutable array

NSMutableArray *myArray = [NSMutableArray arrayWithArray:@[
@"String 2",
@"String 4",
@"String 1",
@"String 3"]];
[myArray sortUsingComparator:
^NSComparisonResult(__strong id obj1, __strong id obj2) {
NSString *string1 = (NSString *)obj1;
NSString *string2 = (NSString *)obj2;
return [string1 compare:string2];
}];

This method takes in a block object (marked by the initial ^ character) that has to return
a value of type NSComparisonResult. This value can be any of the following:
NSOrderedSame

NSOrderedAscending

NSOrderedDescending



1.24 Allocating and Making Use of Dictionaries

NSDictionary *person = @{  //IOS6
@"First Name" : @"Anthony",
@"Last Name" : @"Robbins",
@"Age" : @51
};
NSLog(@"First Name = %@", person[@"First Name"]);
NSLog(@"Last Name = %@", person[@"Last Name"]);
NSLog(@"Age = %@", person[@"Age"]);


NSMutableDictionary *person = [@{
@"First Name" : @"Anthony",
@"Last Name" : @"Robbins",
@"Age" : @51
} mutableCopy];
[person removeObjectForKey:@"Age"];


//enumerate the object and key

[person enumerateKeysAndObjectsUsingBlock:
^(__strong id key, __strong id obj, BOOL *stop) {
NSLog(@"Key = %@, Object For Key = %@", key, obj);
}];

for (id keyInDictionary in [person allKeys]){
id objectForKey = [person objectForKey:keyInDictionary];
NSLog(@"Key = %@, Object For Key = %@", keyInDictionary, objectForKey);
}


NSEnumerator *keys = [person keyEnumerator];
id keyInDictionary = nil;
while ((keyInDictionary = [keys nextObject]) != nil)

{
id objectForKey = [person objectForKey:keyInDictionary];
NSLog(@"Key = %@, Object For Key = %@", keyInDictionary, objectForKey);
}

When using the keyEnumerator method of a mutable dictionary,you are
not allowed to change the values inside the dictionary while going
through the keys
. The same rule, if you remember, applies to mutable
arrays as well..


1.25 Allocating and Making Use of Sets

You would like to store an array of objects but you don’t want any one object to appear
more than once in the array. use NSSet

NSString *hisName = @"Robert";
NSString *hisLastName = @"Kiyosaki";
NSString *herName = @"Kim";
NSString *herLastName = @"Kiyosaki";
NSSet *setOfNames = [[NSSet alloc] initWithObjects:
hisName,
hisLastName,
herName,
herLastName, nil];
NSLog(@"Set = %@", setOfNames);

print result:

Set = {(
Kim,
Robert,
Kiyosaki
)}

It is very important to understand
that a set doesn’t just do a comparison on where in memory an object sits, but it actually
looks into its contents. (如果不是NSString ,而是其他的Object 如何处理???)

NSMutableSet *setOfNames = [[NSMutableSet alloc] initWithObjects:
hisName,
hisLastName, nil];
[setOfNames addObject:herName];
[setOfNames addObject:herLastName];

[setOfNames removeObject:@"Kiyosaki"];
 //只要内容对就可以了,不用原来的variable.

enumerate the NSMutableSet

[setOfNames enumerateObjectsUsingBlock:^(__strong id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSString class]]){
NSString *string = (NSString *)obj;
if ([string isEqualToString:@"Kiyosaki"]){
NSLog(@"Found %@ in the set", string);
*stop = YES;
}
}
}];


allObjects method to get an array of all  the objects in the set

anyObject  return a random object in the set, no matter where in the set it is. You will get nil from this
method if the set is empty.


1.26 Creating Bundles

You want to group your resources into hierarchical structures and be able to access
those resources at runtime with ease.

Follow these steps to successfully create a bundle:
1. Create a root folder on your disk that will later become your bundle. For instance,
let’s give this folder the name Resources.
2. Under the Resources folder, create three more folders named Images, Videos, and
Sounds.
3. Under the three aforementioned folders, place related resources. For instance,
place one or more images in the Images folder and one or more video files under
the Videos folder and so on.
4. Once you are done, rename your Resources folder to Resources.bundle. Once you
add this extension to your folder name, OS X will ask for your confirmation and a
dialog similar to that shown in Figure 1-33 will appear on the screen. Press Add on
the dialog to add the .bundle extension to the Resources folder.

Bundles are simple folders with a .bundle extension. They have two main distinctions
from regular folders:
1. Cocoa Touch provides an interface through which you can access bundles and
their resources really easily.
2. If a bundle is added to the Navigator on the lefthand side of Xcode, any files added
to or removed from the bundle outside Xcode will, respectively, appear in or disappear
immediately from Xcode’s navigator. In contrast, if you had added a normal
folder to Xcode’s navigator and then went and deleted a file from that folder on
disk, without using Xcode’s help, you would see that file marked with red color in
Xcode rather than getting deleted immediately. Bundles can be very useful, especially
if you want to add files to your folders manually using Finder instead of using
Xcode.

确实比normal folder 有用多了

Main bundles are flat bundles, in that all files inside the main bundle will be stored in
one directory (its root directory). Bundles created by programmers can have subdirectories.
Any bundle, including the main bundle, can contain other bundles.

Every iOS application comes with at least one bundle, called the main bundle. The
main bundle contains your app’s binary code and any other resource you are using
inside your application, such as retina images, sounds, HTML files, and whatnot. The
main bundle, in other words, contains the resources that get compiled into your final
binary that you will submit to the App Store or distribute in your organization. These
resources can then be dynamically loaded using the NSBundle class’s mainBundle class
method.



1.27 Loading Data from the Main Bundle

Every app’s main bundle has a flat hierarchy on disk when it is compiled
for submission to App Store. That means all the files that get wrapped
up in your app bundle will be placed on the root folder of the main
bundle. In other words, the main bundle has only one folder, the root
folder, and all files and resources are stored in that folder

{

//load as UIImage

NSString *alanSugarFilePath =[[NSBundle mainBundle] pathForResource:@"AlanSugar"
ofType:@"png"];
if ([alanSugarFilePath length] > 0){
UIImage *image = [UIImage imageWithContentsOfFile:alanSugarFilePath];
if (image != nil){
NSLog(@"Successfully loaded the file as an image.");
} else {
NSLog(@"Failed to load the file as an image.");
}
} else {
NSLog(@"Could not find this file in the main bundle.");
}

}

{//load as NSData

NSString *alanSugarFilePath =
[[NSBundle mainBundle] pathForResource:@"AlanSugar"
ofType:@"png"];
if ([alanSugarFilePath length] > 0){
NSError *readError = nil;
NSData *dataForFile =
[[NSData alloc] initWithContentsOfFile:alanSugarFilePath
options:NSMappedRead
error:&readError];
if (readError == nil &&
dataForFile != nil){
NSLog(@"Successfully loaded the data.");
} else if (readError == nil &&
dataForFile == nil){
NSLog(@"No data could be loaded.");
} else {
NSLog(@"An error occured while loading data. Error = %@", readError);
}
} else {
NSLog(@"Could not find this file in the main bundle.");
}

}

1.28 Loading Data from Other Bundles  (this is what I concern after I read last recipe)

You have included a few images or other resources in a separate bundle inside your
main bundle and you would like to access those resources at runtime. (这么说其实App bundle 里面只有一个main bundle, 我们自己创建的拖进去就变成mainBundle's children),

Find the path to your bundle at runtime using the pathForResource:ofType: method of
your main bundle. Once you have the path to your bundle, simply access it using the
bundleWithPath: class method of NSBundle.

so Need to locate our bundle in the main bundle, then construct our NSBundle object.

{

NSString *resourcesBundlePath =
[[NSBundle mainBundle] pathForResource:@"MyBundle"
ofType:@"bundle"];
if ([resourcesBundlePath length] > 0){

//after construct this bundle, the operation is the same as the main bundle

NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcesBundlePath];

if (resourcesBundle != nil){
NSString *pathToAlanSugarImage =
[resourcesBundle pathForResource:@"AlanSugar"
ofType:@"png"
inDirectory:@"Images"];
if ([pathToAlanSugarImage length] > 0){
UIImage *image = [UIImage imageWithContentsOfFile:pathToAlanSugarImage];
if (image != nil){
NSLog(@"Successfully loaded the image from the bundle.");
} else {
NSLog(@"Failed to load the image.");
}
} else {
NSLog(@"Failed to find the file inside the bundle.");
}
} else {
NSLog(@"Failed to load the bundle.");
}
} else {
NSLog(@"Could not find the bundle.");
}

}

If you are attempting to find all the resources which are stored in a specific folder inside
a bundle, you can use the pathsForResourcesOfType:inDirectory: method of the
NSBundle class. In this code, we will attempt to find the path to all the .png files inside
the Images folder of our Resources.bundle bundle:

{

  NSString *resourcesBundlePath =
[[NSBundle mainBundle] pathForResource:@"Resources"
ofType:@"bundle"];
if ([resourcesBundlePath length] > 0){
NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcesBundlePath];
if (resourcesBundle != nil){
NSArray *PNGPaths = [resourcesBundle pathsForResourcesOfType:@"png"
inDirectory:@"images"];
[PNGPaths
enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"Path %lu = %@", (unsigned long)idx+1, obj);
}];
} else {
NSLog(@"Failed to load the bundle.");
}
} else {
NSLog(@"Could not find the bundle.");
}

}

1.29 Sending Notifications with NSNotificationCenter

You want to broadcast an event in your app and allow any object that is willing to listen
to it to take action, depending on the notification that you are broadcasting.

Use the postNotificationName:object:userInfo: method of the default notification
center of type NSNotificationCenter to post a notification that carries an object (usually
the object that fires the notification) and a user-info dictionary that can carry extra
information about the notification and/or the object that fires the notification.

Notification centers are dispatch centrals for notification objects. For instance, when the
keyboard pops up anywhere while the user is inside your app, iOS will send a notification
to your app. Any object inside your app willing to listen to this notification can
add itself to the default notification center as an observer for that particular notification.
Once your object’s lifetime comes to an end, it must remove itself from the notification
center’s dispatch table.
As a result, a notification is a message that gets broadcasted to
observers through a notification center. A notification center is an instance of
NSNotificationCenter class. We retrieve the default notification center object using the
defaultCenter class method of NSNotificationCenter.

Notifications are objects of type NSNotification. A notification object has a name
(specified as NSString) and can carry two key pieces of information:

Sender Object
This is the instance of the object that fires the notification. The observer can access
this object using the object instance method of the NSNotification class.

User-Info Dictionary
This is an optional dictionary that the sender object can create and send alongside
a notification object. This dictionary usually contains more information about the
notification. For instance, when a keyboard is about to get displayed in iOS for any

component inside your app, iOS sends the UIKeyboardWillShowNotification notification
to the default notification center. The user-info dictionary of this notification
contains values such as the rectangle of the keyboard before and after
animation and the animation duration of the keyboard. Using this data, an observer
can make a decision as to, for instance, what to do with UI components that potentially
will be obstructed once the keyboard gets displayed on the screen.


However, there is one potential caveat about notifications:
they are not delivered immediately. They are dispatched by notification
centers, and the implementation of NSNotificationCenter is hidden
from application programmers. Delivery might sometimes be delayed
by a few milliseconds or, in extreme cases (which I have never encountered),
a few seconds. As a result, it is up to you to decide where to and
where not to use notifications.

In order to construct a notification of type NSNotification, use the notificationWith
Name:object:userInfo: class method of the NSNotificationClass, as we will soon see.

It is best to suffix your notification names with the word Notification.
For instance, it is permitted to give your notification a name similar to
ResultOfAppendingTwoStrings. However, it is better to give the name
ResultOfAppendingTwoStringsNotification, as that clearly says what
this name belongs to.

#import "AppDelegate.h"
@implementation AppDelegate
/* The notification name */
const NSString *ResultOfAppendingTwoStringsNotification =
@"ResultOfAppendingTwoStringsNotification";
/* Keys inside the dictionary that our notification sends */
const NSString
*ResultOfAppendingTwoStringsFirstStringInfoKey = @"firstString";
const NSString
*ResultOfAppendingTwoStringsSecondStringInfoKey = @"secondString";
const NSString
*ResultOfAppendingTwoStringsResultStringInfoKey = @"resultString";

{

NSString *firstName = @"Anthony";
NSString *lastName = @"Robbins";
NSString *fullName = [firstName stringByAppendingString:lastName];
NSArray *objects = [[NSArray alloc] initWithObjects:
firstName,
lastName,
fullName,
nil];
NSArray *keys = [[NSArray alloc] initWithObjects:
ResultOfAppendingTwoStringsFirstStringInfoKey,
ResultOfAppendingTwoStringsSecondStringInfoKey,
ResultOfAppendingTwoStringsResultStringInfoKey,
nil];
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjects:objects
forKeys:keys];
NSNotification *notificationObject =
[NSNotification
notificationWithName:(NSString *)ResultOfAppendingTwoStringsNotification
object:self
userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:notificationObject];

}

If you are planning on not sending an object or a user-info dictionary, then I suggest
you use the postNotificationName:object: instance method of NSBundle. Specify a
string that represents the name of your notification as the first parameter, and nil as
the second parameter, which is the object that should be carried with the notification.
Here is an example:

{

[[NSNotificationCenter defaultCenter]
postNotificationName:(NSString *)NetworkConnectivityWasFoundNotification
object:nil];  //好简单就一个key

}

1.30 Listening for Notifications Sent from  NSNotificationCenter

Add your observer object to the notification center using theaddObserver:selector:name:object: instance method of NSNotificationCenter before a notification isbroadcast. To stop observing a notification, use theremoveObserver:name:object: instance  method of NSNotificationCenter and pass your observer object, then the name  of the notification that you want to stop observing and the object that you originally
subscribed to

Two notifications with the samename can be broadcast, but they must come from two different objects.

You can specify this source object (broadcaster)when you start listening for notifications, using the object parameter of the  addObserver:selector:name:object:   method of the notification center.

Here is a brief description of each of the parameters that the addObserver:selec
tor:name:object: accepts:
addObserver
The object that will receive the notifications (observer).
selector
The selector (method) to be called on the observer when the notification is broadcasted
and received by the observer. This method takes a single argument of type
NSNotification.
name
The name of the notification to observe.
object
Optionally specifies the source of the broadcast notification. If this parameter is nil, notifications of the specified name will be received by the observer regardless  of which object broadcasts them. If this parameter is set, only the notifications of  the specified name that are broadcast by the given object will be observed.

{

/* Listen for the notification */
[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(appendingIsFinished:)
name:(NSString *)ResultOfAppendingTwoStringsNotification
object:self];

}

//do remember this action to remove it.

- (void)applicationWillTerminate:(UIApplication *)application{
/* We no longer observe ANY notifications */
[[NSNotificationCenter defaultCenter] removeObserver:self];
}








































 







 

















 

 
















 

 











CSDN海神之光上传的代码均可运行,亲测可用,直接替换数据即可,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b或2023b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描博客文章底部QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+传输+分析+去噪(CEEMDAN)、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 1. EMD(经验模态分解,Empirical Mode Decomposition) 2. TVF-EMD(时变滤波的经验模态分解,Time-Varying Filtered Empirical Mode Decomposition) 3. EEMD(集成经验模态分解,Ensemble Empirical Mode Decomposition) 4. VMD(变分模态分解,Variational Mode Decomposition) 5. CEEMDAN(完全自适应噪声集合经验模态分解,Complementary Ensemble Empirical Mode Decomposition with Adaptive Noise) 6. LMD(局部均值分解,Local Mean Decomposition) 7. RLMD(鲁棒局部均值分解, Robust Local Mean Decomposition) 8. ITD(固有时间尺度分解,Intrinsic Time Decomposition) 9. SVMD(逐次变分模态分解,Sequential Variational Mode Decomposition) 10. ICEEMDAN(改进的完全自适应噪声集合经验模态分解,Improved Complementary Ensemble Empirical Mode Decomposition with Adaptive Noise) 11. FMD(特征模式分解,Feature Mode Decomposition) 12. REMD(鲁棒经验模态分解,Robust Empirical Mode Decomposition) 13. SGMD(辛几何模态分解,Spectral-Grouping-based Mode Decomposition) 14. RLMD(鲁棒局部均值分解,Robust Intrinsic Time Decomposition) 15. ESMD(极点对称模态分解, extreme-point symmetric mode decomposition) 16. CEEMD(互补集合经验模态分解,Complementary Ensemble Empirical Mode Decomposition) 17. SSA(奇异谱分析,Singular Spectrum Analysis) 18. SWD(群分解,Swarm Decomposition) 19. RPSEMD(再生相移正弦辅助经验模态分解,Regenerated Phase-shifted Sinusoids assisted Empirical Mode Decomposition) 20. EWT(经验小波变换,Empirical Wavelet Transform) 21. DWT(离散小波变换,Discraete wavelet transform) 22. TDD(时域分解,Time Domain Decomposition) 23. MODWT(最大重叠离散小波变换,Maximal Overlap Discrete Wavelet Transform) 24. MEMD(多元经验模态分解,Multivariate Empirical Mode Decomposition) 25. MVMD(多元变分模态分解,Multivariate Variational Mode Decomposition)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值