!!!Obj-c on Mac --- Chapter 2 ~ 4

本文深入探讨了Objective-C编程语言的基础知识、文件扩展名、编译过程、框架使用、Cocoa框架介绍、NSLog()函数、BOOL类型处理、方法调用和实例变量等核心概念,为开发者提供了一次全面的编程之旅。

Chapter 2 Extensions to C

Xcode uses the .m extension to indicate a file that holds Objective- C code and will be processed by the Objective- C compiler. File names ending in .c are handled by the C compiler, and .cpp files are the province of the C++ compiler. (In Xcode, all this compiling is handled by the GNU Compiler Collection [GCC], a single compiler that understands all three variations of the language.)

That Wacky #import Thing

#import is a feature provided by the GCC compiler, which is what Xcode uses when you’re compiling Objective- C, C, and C++ programs. #import guarantees that a header file will be included only once, no matter how many times the #import directive is actually seen for that file.

  • In C, programmers typically use a scheme based on the #ifdef directive to avoid the situation where one file includes a second file, which then, recursively, includes the first.
  • In Objective- C, programmers use #import to accomplish the same thing.

A framework is a collection of parts—header files, libraries, images, sounds, and more—collected together into a single unit.

Cocoa consists of a pair of frameworks, Foundation and Application Kit (also known as AppKit), along with a suite of supporting frameworks, including Core Animation and Core Image, which add all sorts of cool stuff to Cocoa.

The Foundation framework handles features found in the layers beneath the user interface, such as data structures and communication mechanisms.

Each framework has a master header file that includes all the framework’s individual header files. By using #import on the master header file, you have access to all the framework’s features.

When you include the master header file with #import <Foundation/Foundation.h>, you get all Foundation header files.

NSLog() and @”strings”

NSLog() is a Cocoa function that works very much like printf().

Cocoa prefixes all its function, constant, and type names with “NS”. The prefix helps prevent name collisions

A string in double quotes preceded by an at sign means that the quoted string should be treated as a Cocoa NSString element.

#import <Foundation/Foundation.h>
int main (int argc, const char *argv[])
{
NSLog (@"Hello, Objective- C!");
return (0);
} // main

Are You the Boolean Type?

BOOL in Objective- C is actually just a type definition (typedef) for the signed character type (signed char), which uses 8 bits of storage. YES is defined as 1 and NO as 0 (using #define).


Objective-C doesn’t treat BOOL as a true Boolean type that can hold only YES or NO values. The compiler considers BOOL to be an 8- bit number, and the values of YES and NO are just a convention. This causes a subtle gotcha: if you inadvertently assign an integer value that’s more than 1 byte long, such as a short or an int value, to a BOOL variable, only the lowest byte is used for the value of the BOOL. If that byte happens to be zero (as with 8960, which in hexadecimal is 0x2300), the BOOL value will be zero, the NO value.

// Correct Code
BOOL areIntsDifferent (int thing1, int thing2)
{
    if (thing1 == thing2) {
        return (NO);
    } else {
        return (YES);
    }
} // areIntsDifferent

BOOL areIntsDifferent_faulty (int thing1, int thing2)
{
return (thing1 - thing2);
} // areIntsDifferent_faulty

if(areIntsDifferent_faulty(8, 25) == YES)         // the return value is not equal to YES
if(areIntsDifferent_faulty(8,25))                 // this is safe, as NO is always 0
when you print the values of arbitrary objects with NSLog(), you’ll use the%@ format specification. When you use this specifier, the object supplies its own NSLog() format via a method named description. The description method for NSString simply prints the string’s characters.

Chapter 3 Introduction to Object- Oriented Programming

Indirection Through Filenames

#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
    const char *words[4] = { "aardvark", "abacus",
                            "allude", "zygote" };
    int wordCount = 4;
    int i;
    for (i = 0; i < wordCount; i++) {
        NSLog (@"%s is %d characters long", words[i], strlen(words[i]));
    }
    return (0);
} // main
We use %s, because words is an array of C strings rather than of @"NSString" objects.

OOP in Objective- C

It’s important to remember that the colon is a very significant part of the method’s name. The method

- (void) scratchTheCat;
is distinct from

- (void) scratchTheCat: (CatType) critter;
A common mistake made by many freshly minted Objective-C programmers is to indiscriminantly add a colon to the end of a method name that has no arguments. In the face of a compiler error, you might be tempted to toss in an extra colon and hope it fixes things. The rule to follow is this: If a method takes an argument, it has a colon. If it takes no arguments, it has no colons.

The @interface section, which we just discussed, defines a class’s public interface. The interface is often called theAPI, which is a TLA for “application programming interface” (and TLA is a TLA for “three- letter acronym”).

You might think that defining a method solely in the @implementation directive makes it inaccessible from outside the implementation, but that’s not the case. Objective- C doesn’t really have private methods. There is no way to mark a method as being private and preventing other code from calling it. This is a side effect of Objective- C’s dynamic nature.

Because an object’s local variables are specific to that instance of the object, we call them instance variables, often shortened to “ivars.”

Chapter 4 Inheritance

method dispatching

NSObject declares one instance variable, called isa, which holds the pointer to the object’s class.

Instance Variable

Every method call gets a hidden parameter, called self, which is a pointer to the object that receives the message.

self points to the first instance variable of the first class in the chain of inheritance.

The compiler works its magic by using a “base plus offset” mechanism. Given the base address of an object— that is, the memory location of the first byte of the first instance variable—the compiler can find all other instance variables by adding an offset to that address.

For example, if the base address of the rounded rectangle object is 0x1000, the isa instance variable is at 0x1000 + 0, which is 0x1000. isa is a 4- byte value, so the next instance variable, fillColor, starts at an offset of four, at 0x1000 + 4, or 0x1004. Every instance variable has an offset from the object’s base.
When you access the fillColor instance variable in a method, the compiler generates code to take the value that self holds and add the value of the offset (4, in this case) to point to the location where the variable’s value is stored.
This does lead to problems over time. These offsets are now hard- coded into the program generated by the compiler. Even if Apple’s engineers wanted to add another instance variable to NSObject, they couldn’t, because that would change all of the instance variable offsets. This is called the fragile base class problem.
Apple has fixed this problem with the new 64- bit Objective- C runtime introduced with Leopard, which uses indirection for determining ivar locations.

Overriding Methods

super vs. self              P70

When you override a method, invoking the superclass method is almost always a good idea, in case it’s doing more work than you’re aware of.

<think>我们分析条件:`if (!download_diag_obj->numberOfConnections || download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections)` 这个条件由两个子条件通过逻辑或(OR)连接组成,判断的是连接数参数是否有效。 具体拆解: 1. `!download_diag_obj->numberOfConnections` - 含义:检查`numberOfConnections`是否为0(或假值)。在C语言中,数值为0时逻辑判断为假,取非则为真;非0为真,取非为假。 - 作用:判断连接数是否未设置(即为0)或者设置为0(因为0个连接没有意义)。 2. `download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections` - 含义:检查设置的连接数是否超过了最大允许连接数(`downloadDiagnosticMaxConnections`)。 因此,整个条件判断的是:如果连接数未设置(为0)或者设置的连接数超过了允许的最大值,则条件成立,进入错误处理分支。 在错误处理分支中: - 记录错误日志(TR143_ERROR) - 将配置中的连接数(`pCfg->num_of_conn`)设置为默认值(`download_diag_obj->X_TP_DownDefConns`) - 同时,修正源数据(`download_diag_obj->numberOfConnections`)为默认值,以确保后续使用的一致性。 如果条件不成立(即连接数有效,非0且不超过最大值),则直接使用设置的连接数。 所以,这个条件的作用是确保连接数在有效范围内(1到最大值之间),否则使用默认值并修正源数据。 §§相关问题§§ 1. 为什么在条件中要检查`numberOfConnections`为0(即`!download_diag_obj->numberOfConnections`)?在实际应用中,设置连接数为0可能表示什么? 2. 如果`downloadDiagnosticMaxConnections`的值被错误设置为0,这个条件判断会有什么后果? 3. 在错误处理分支中,为什么要同时修改配置结构体(`pCfg->num_of_conn`)和源数据对象(`download_diag_obj->numberOfConnections`)的值? 4. 这个条件判断是否考虑到了负数连接数的情况?如果传入负数会如何处理? 5. 在TR369模式下,同样的有效性判断使用了参数结构体`pParm`而非`download_diag_obj`,这是为什么? </think>以下是针对条件判断 `if (!download_diag_obj->numberOfConnections || download_diag_obj->numberOfConnections > download_diag_obj->downloadDiagnosticMaxConnections)` 的详细解析: ### 条件判断分析 该条件由两个子条件通过逻辑或(`||`)组合而成,用于验证连接数参数的有效性: #### 1. **第一子条件:`!download_diag_obj->numberOfConnections`** - **含义**:检测连接数是否为**无效值** - **具体判断**: - 当 `numberOfConnections` 等于 `0` 时成立(0 在布尔判断中为假,`!` 取反为真) - 当 `numberOfConnections` 为 `NULL` 时成立(指针类型的特殊判断) - **设计目的**: - 确保连接数配置不能为零(零连接无意义) - 防止未初始化的空指针导致程序崩溃 #### 2. **第二子条件:`numberOfConnections > downloadDiagnosticMaxConnections`** - **含义**:检测连接数是否**超过系统上限** - **具体判断**: - 当设置的连接数大于系统允许的最大连接数时成立 - **设计目的**: - 防止资源过载(如内存耗尽或网络拥塞) - 确保诊断测试在安全范围内运行 #### 3. **组合逻辑:逻辑或(`||`)** - **触发条件**:任意一个子条件成立即进入错误处理分支 - **错误处理内容**: ```c TR143_ERROR(...); // 记录错误日志 pCfg->num_of_conn = 默认值; // 使用默认连接数 download_diag_obj->numberOfConnections = 默认值; // 修正源数据 ``` ### 设计意图图解 ```mermaid graph TD A[连接数检查] --> B{是否为0/NULL?} A --> C{是否超过最大值?} B -->|是| D[判定无效] C -->|是| D D --> E[记录错误日志] E --> F[使用默认值] F --> G[修正源数据] B -->|否| H[有效] C -->|否| H H --> I[使用原值] ``` ### 典型应用场景 1. **新设备初始化**: - `numberOfConnections` 默认为0 - 触发条件一 → 使用默认值10 2. **错误配置**: - 管理员误设连接数=1000 - 系统上限=500 → 触发条件二 → 自动修正为默认值 3. **空指针防护**: - 内存分配失败导致指针为NULL - 触发条件一 → 避免程序崩溃
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值