『壹』 ios 怎麼設置一個全局的變數
方法1:使用靜態變數 (不推薦)
方法2: 使用singleton pattern
方法3:把全局變數設置到AppDelegate中
例: 定義和使用一個全局變數"isLogin"
AppDelegate.h
@interface AppDelegate :UIResponder <UIApplicationDelegate>
@property (strong,nonatomic)UIWindow *window;
@propertyBOOL isLogin;
@end
AppDelegate.m
@implementation AppDelegate
@synthesize window =_window;
@synthesize isLogin;
@end
那麼在其他的class里,則可以通過下列代碼調用全局變數
AppDelegate *delegate=(AppDelegate*)[[]delegate];
delegate.isLogin=YES;
『貳』 ios class 怎麼引入類
選擇File - New - File - ios - cocoatouch - Objective-C class(MAC開發同理),並且填寫繼承的父類,即創建出類。 引用創建的類僅需#import 「你要引用的類名.h」
『叄』 ios protocal和class的區別
是Protocol吧?
Protocol:協議(Protocol)將兩個繼承關系很遠的類聯系起來。
Class:
到目前為止,我們已經知道了對應於方法的SEL數據類型,和SEL同樣在Objective-C裡面我們不僅僅可以使用對應於方法的SEL,對於類在
Objective-C也為我們准備了類似的機制,Class類型。當一個類被正確的編譯過後,在這個編譯成功的類裡面,存在一個變數用於保存這個類的信
息。我們可以通過一個普通的字元串取得
這個Class,也可以通過我們生成的對象取得這個Class。Class被成功取得之後,我們可以把這個Class當作一個已經定義好的類來使用它。這
樣的機制允許我們在程序執行的過程當中,可以Class來得到對象的類,也可以在程序執行的階段動態的生成一個在編譯階段無法確定的一個對象。
因為Class裡面保存了一個類的所有信息,當然,我們也可以取得一個類的超類。關於Class類型,具體的使用格式如下:
1Class變數名=[類或者對象class];
2Class變數名=[類或者對象superclass];
3Class變數名=NSClassFromString(方法名字的字元串);
4NSString*變數名=NSStringFromClass(Class參數);
第一行代碼,是通過向一個類或者對象發送class消息來獲得這個類或者對象的Class變數。
第二行代碼,是通過向一個類或者對象發送superclass消息來獲得這個類或者對象的超類的Class變數。
第三行代碼,是通過調用NSClassFromString函數,並且把一個字元串作為參數來取得Class變數。這個在我們使用配置文件決定執行的時候的類的時候,NSClassFromString給我們帶來了極大的方便。
第四行代碼,是NSClassFromString的反向函數NSStringFromClass,通過一個Class類型作為變數取得一個類的名字。
當我們在程序裡面通過使用上面的第一,二或者第三行代碼成功的取得一個Class類型的變數,比如說我們把這個變數名字命名為myClass,那麼我們在
以後的代碼種可以把myClass當作一個我們已經定義好的類來使用,當然我們可以把這個變數作為參數傳遞到其他的方法當中讓其他的方法動態的生成我們需
要的對象。
『肆』 ios 怎麼調用分類裡面的方法
ios category類別的使用
Objective-C提供了一個非常靈活的類(Class)擴展機制-類別(Category)。類別用於對一個已經存在的類添加方法(Methods)。你只需要知道這個類的公開介面,不需要知道類的源代碼。需要注意的是,類別不能為已存在的類添加實例變數(Instance Variables)。
類別的基本語法如下:
@interface ClassName(CategoryName)
//method declarations
@end
@interface 類名(類別名)
類別方法申明
@end
注意幾點:
1.現有類的類名位於 @interface之後
2.括弧中是類別的名稱(只要名稱唯一,可以添加任意多的類別)
3.類別沒有實例變數部分
類別的語法與類的語法非常相似。類別的方法就是類的方法。類別的定義可以放在一個單獨的文件中("類別名.h"), 也可以放在一個已存在的類的定義文件中(.h文件)。類別的實現則可放在一個單獨的「類別名.m」文件中,或另一個類的實現文件中。這點也與類的定義相似。因為類別的方法就是類的方法,所以類別的方法可以自由引用類的實例變數(無論公有或私有)。
子類(subclassing)是進行類擴展的另一種常用方法。與子類相比,類別最主要的優點是:系統中已經存在的類可以不需修改就可使用類別的擴展功能。例如,假設系統中存在一個類A;另外一個類B中定義了一個類A類型的實例變數,並包含了類A的頭文件「#import <A.h>"。假設一段時間後,需要對類A擴展幾個新的方法。如果用子類,就需要創建一個子類A-1。如果類B想要使用類A的新方法,就要進行如下修改:1) 將包含的頭文件改為"#import<A-1.h>"; 2)將所有用到的類A對象改為類A-1的對象。可以想像,如何有很多類需要用到類A的新功能(比如類A是iOS中的類UIViewController),隨著系統的升級(iOS從1.0到5.0),你的程序需要不停地進行這種繁瑣地修改。如果使用類別,即使類A升級了,系統中其它的類可以不需任何修改,直接就可以調用類A的新方法。
類別的第二大優點是實現了功能的局部化封裝。類別定義可以放在一個已存在的類(類A)的定義文件中(.h)。這意味著這個類別只有在類A被引用的前提下才會被外部看到。如果另一個類(類B)不需要用到類A的功能(沒有包含類A的.h文件),也就不會看到依附類A存在的類別。iOS SDK中廣泛運用這種類別定義法來封裝功能。例如,在 UINavigationController.h中定義了專為UINavigationController擴展的UIViewController類別:
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
@property(nonatomic,readonly,retain) UINavigationController *navigationController;
......
@end
如果一個類不引用UINavigationController.h,也就不會看到navigationItem和navigationController這兩個性質申明(declared property)。
類別的另一個優點是輕巧(light-weight)。很多時候,對已存在的類所需的擴展僅僅是幾個新方法。這時,用類別避免了在系統中留下很多非常短小的「微」子類,使程序更加緊湊。
歸納:
1、實現類別
同實現類相似,實現方法即可
2、 類別的局限性
1.類別不能添加新的實例變數
2.命名沖突,如果類別中方法和類中已有方法同名,則類別具有更高優先順序
3 類別的作用
1.將類的實現分散到多個不同文件或多個不同框架中
2.創建私有方法的前向引用
3.向對象添加非正式協議
4 利用類別分散實現
利用類別可以將類的方法分散到多個源文件中
特別指出的是:類別可以訪問其繼承的類的實例變數
在使用一個方法時,對象的方法是在介面中聲明、父類中聲明、還是類別中聲明並不重要
類別不僅可以分散實現到不同源文件,也可跨框架
5、 使用類別創建前向引用
雖然可以實現未聲明的方法,但是編譯器會提出警告
通過類別可以提供聲明,而且,聲明的方法不必要一定在類別的實現中實現,也可以在類的實現中實現
6、 非正式協議和委託類別
委託(delegage)是一種對象,另一個類的對象會要求委託對象執行它的某些操作
委託對象接受其它對象對它的特定方法的調用
其實就是委託對象必須實現別的對象調用的方法,與介面類似
7、 ITunesFinder項目
8 、委託和類別
委託和類別有什麼關系?委託強調類別的另一種應用:被發送給委託對象的方法可以聲明為一個NSObject的類別
創建一個NSObject的類別稱為「創建一個非正式協議」
9、 響應選擇器
選擇器只是一個方法名稱,可以使用@selector()預編譯指令指定選擇器,其中方法名位於圓括弧中,但它以OC運行時使用的特殊方式編碼,以快速執行查詢
NSObject提供了一個respondsToSelector的方法,詢問對象以確定其是否實現某個特定消息
10、 選擇器的其他應用
選擇器可以被傳遞,可以作為方法參數,甚至可以作為實例變數存儲
『伍』 ios class 怎麼引入類
選擇File - New - File - ios - cocoatouch - Objective-C class(MAC開發同理),並且填寫繼承的父類,即創建出類。 引用創建的類僅需#import 「你要引用的類名.h」。
『陸』 ios 怎麼動態向已有類添加屬性
在ios運行過程中,有幾種方式能夠動態的添加屬性。
1-通過runtime動態關聯對象
主要用到了objc_setAssociatedObject,objc_getAssociatedObject以及objc_removeAssociatedObjects
//在目標target上添加關聯對象,屬性名propertyname(也能用來添加block),值value
+ (void)addAssociatedWithtarget:(id)target withPropertyName:(NSString *)propertyName withValue:(id)value {
id property = objc_getAssociatedObject(target, &propertyName);
if(property == nil)
{
property = value;
objc_setAssociatedObject(target, &propertyName, property, OBJC_ASSOCIATION_RETAIN);
}
}
//獲取目標target的指定關聯對象值
+ (id)getAssociatedValueWithTarget:(id)target withPropertyName:(NSString *)propertyName {
id property = objc_getAssociatedObject(target, &propertyName);
return property;
}
優點:這種方式能夠使我們快速的在一個已有的class內部添加一個動態屬性或block塊。
缺點:不能像遍歷屬性一樣的遍歷我們所有關聯對象,且不能移除制定的關聯對象,只能通過removeAssociatedObjects方法移除所有關聯對象。
2-通過runtime動態添加Ivar
主要用到objc_allocateClassPair,class_addIvar,objc_registerClassPair
//在目標target上添加屬性(已經存在的類不支持,可跳進去看注釋),屬性名propertyname,值value
+ (void)addIvarWithtarget:(id)target withPropertyName:(NSString *)propertyName withValue:(id)value {
if (class_addIvar([target class], [propertyName UTF8String], sizeof(id), log2(sizeof(id)), "@")) {
YYLog(@"創建屬性Ivar成功");
}
}
//獲取目標target的指定屬性值
+ (id)getIvarValueWithTarget:(id)target withPropertyName:(NSString *)propertyName {
Ivar ivar = class_getInstanceVariable([target class], [propertyName UTF8String]);
if (ivar) {
id value = object_getIvar(target, ivar);
return value;
} else {
return nil;
}
}
優點:動態添加Ivar我們能夠通過遍歷Ivar得到我們所添加的屬性。
缺點:不能在已存在的class中添加Ivar,所有說必須通過objc_allocateClassPair動態創建一個class,才能調用class_addIvar創建Ivar,最後通過objc_registerClassPair注冊class。
3-通過runtime動態添加property
主要用到class_addProperty,class_addMethod,class_replaceProperty,class_getInstanceVariable
//在目標target上添加屬性,屬性名propertyname,值value
+ (void)addPropertyWithtarget:(id)target withPropertyName:(NSString *)propertyName withValue:(id)value {
//先判斷有沒有這個屬性,沒有就添加,有就直接賦值
Ivar ivar = class_getInstanceVariable([target class], [[NSString stringWithFormat:@"_%@", propertyName] UTF8String]);
if (ivar) {
return;
}
/*
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C =
objc_property_attribute_t backingivar = { "V", "_privateName" };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_addProperty([SomeClass class], "name", attrs, 3);
*/
//objc_property_attribute_t所代表的意思可以調用getPropertyNameList列印,大概就能猜出
objc_property_attribute_t type = { "T", [[NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([value class])] UTF8String] };
objc_property_attribute_t ownership = { "&", "N" };
objc_property_attribute_t backingivar = { "V", [[NSString stringWithFormat:@"_%@", propertyName] UTF8String] };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
if (class_addProperty([target class], [propertyName UTF8String], attrs, 3)) {
//添加get和set方法
class_addMethod([target class], NSSelectorFromString(propertyName), (IMP)getter, "@@:");
class_addMethod([target class], NSSelectorFromString([NSString stringWithFormat:@"set%@:",[propertyName capitalizedString]]), (IMP)setter, "v@:@");
//賦值
[target setValue:value forKey:propertyName];
NSLog(@"%@", [target valueForKey:propertyName]);
YYLog(@"創建屬性Property成功");
} else {
class_replaceProperty([target class], [propertyName UTF8String], attrs, 3);
//添加get和set方法
class_addMethod([target class], NSSelectorFromString(propertyName), (IMP)getter, "@@:");
class_addMethod([target class], NSSelectorFromString([NSString stringWithFormat:@"set%@:",[propertyName capitalizedString]]), (IMP)setter, "v@:@");
//賦值
[target setValue:value forKey:propertyName];
}
}
id getter(id self1, SEL _cmd1) {
NSString *key = NSStringFromSelector(_cmd1);
Ivar ivar = class_getInstanceVariable([self1 class], "_dictCustomerProperty"); //basicsViewController裡面有個_dictCustomerProperty屬性
NSMutableDictionary *dictCustomerProperty = object_getIvar(self1, ivar);
return [dictCustomerProperty objectForKey:key];
}
void setter(id self1, SEL _cmd1, id newValue) {
//移除set
NSString *key = [NSStringFromSelector(_cmd1) :NSMakeRange(0, 3) withString:@""];
//首字母小寫
NSString *head = [key substringWithRange:NSMakeRange(0, 1)];
head = [head lowercaseString];
key = [key :NSMakeRange(0, 1) withString:head];
//移除後綴 ":"
key = [key :NSMakeRange(key.length - 1, 1) withString:@""];
Ivar ivar = class_getInstanceVariable([self1 class], "_dictCustomerProperty"); //basicsViewController裡面有個_dictCustomerProperty屬性
NSMutableDictionary *dictCustomerProperty = object_getIvar(self1, ivar);
if (!dictCustomerProperty) {
dictCustomerProperty = [NSMutableDictionary dictionary];
object_setIvar(self1, ivar, dictCustomerProperty);
}
[dictCustomerProperty setObject:newValue forKey:key];
}
+ (id)getPropertyValueWithTarget:(id)target withPropertyName:(NSString *)propertyName {
//先判斷有沒有這個屬性,沒有就添加,有就直接賦值
Ivar ivar = class_getInstanceVariable([target class], [[NSString stringWithFormat:@"_%@", propertyName] UTF8String]);
if (ivar) {
return object_getIvar(target, ivar);
}
ivar = class_getInstanceVariable([target class], "_dictCustomerProperty"); //basicsViewController裡面有個_dictCustomerProperty屬性
NSMutableDictionary *dict = object_getIvar(target, ivar);
if (dict && [dict objectForKey:propertyName]) {
return [dict objectForKey:propertyName];
} else {
return nil;
}
}
優點:這種方法能夠在已有的類中添加property,且能夠遍歷到動態添加的屬性。
缺點:比較麻煩,getter和setter需要自己寫,且值也需要自己存儲,如上面的代碼,我是把setter中的值存儲到了_dictCustomerProperty裡面,在getter中再從_dictCustomerProperty讀出值。
4-通過setValue:forUndefinedKey動態添加鍵值
這種方法優點類似property,需要重寫setValue:forUndefinedKey和valueForUndefinedKey:,存值方式也一樣,需要藉助一個其它對象。由於這種方式沒通過runtime,所以也比較容易理解。
『柒』 iOS中import和include,class的區別
1。import和include都是包含某個文件
2.import可以防止重復包含
3.class是聲明有這個類,具體怎麼實現沒包括
『捌』 ios為什麼class
#import是引入頭文件和類庫的,@class適用於前向聲明一個類。但是沒有引入,需要用這個類時,還是如要把這個類的頭文件給improt進來的
『玖』 iOS開發中#import,include和@class的區別解析
#import與@class的區別
1.import會包含這個類的所有信息,包括實體變數和方法,而@class只是告訴編譯器,其後面聲明的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,後面會再告訴你。
2.在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變數和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。 而在實現類裡面,因為會用到這個引用類的內部的實體變數和方法,所以需要使用#import來包含這個被引用類的頭文件。
3.在編譯效率方面考慮,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,後面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。
4.如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那麼就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。
所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個類型來用的。 在實現這個介面的實現類中,如果需要引用這個類的實體變數或者方法之類的,還是需要import在@class中聲明的類進來.
#import和#include的區別
當我們在代碼中使用兩次#include的時候會報錯:因為#include相當於拷貝頭文件中的聲明內容,所以會報重復定義的錯誤
但是使用兩次#import的話,不會報錯,所以他可以解決重復導入的問題,他會做一次判斷,如果已經導入一次就不導入了