三元條件表達(dá)式的兩元使用
1> 使用格式
表達(dá)式A ? 表達(dá)式B : 表達(dá)式C
2> 運(yùn)算結(jié)果
如果表達(dá)式A成立,也就是為“真”,條件運(yùn)算符的結(jié)果就是表達(dá)式B的值,否則,就為表達(dá)式C的值
3> 三元條件表達(dá)式?:是C中唯一一個(gè)三目運(yùn)算符,用來替代簡單的if-else語句,同時(shí)也是可以兩元使用的
!self.completion ?: self.completion(self.userInfo);
等同于
if(self.completion){
self.completion(self.userInfo);
}
括號(hào)中的復(fù)合語句
A compound statement enclosed in parentheses 來自gnc的解釋
源代碼定義:
RETURN_VALUE_RECEIVER = {(
// your code
RETURN_VALUE; // 返回值
)};
*下面是一些例子
例子1:
self.tempBtn = ({
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(100, 100, 50, 50);
[button setTitle:@"測試" forState:UIControlStateNormal];
button;
});
例子2:
// 添加myTableView
_myTableView = ({
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.backgroundColor = [UIColor clearColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[tableView registerClass:[TweetCell class] forCellReuseIdentifier:kCellIdentifier_Tweet];
[self.view addSubview:tableView]
tableView;
});
Note:
1.它最大的意義在于將代碼整理分塊,將同一個(gè)邏輯層級(jí)的代碼包在一起
2.同時(shí)對于一個(gè)無需復(fù)用小段邏輯,也免去了重量級(jí)的調(diào)用函數(shù),
3.返回值和代碼塊結(jié)束點(diǎn)必須在結(jié)尾
RAC 倒計(jì)時(shí)
#define kMaxLimitCount 10
@weakify(self);
__wea NSInteger number = 0;
RACSignal *timer = [[[RACSignal interval:1.0f onScheduler:[RACScheduler mainThreadScheduler]] map:^id _Nullable(NSDate * _Nullable value) {
@strongify(self);
if (--number <= 0) {
[self.goBackBtn setTitle:@"獲取驗(yàn)證碼" forState:UIControlStateNormal];
return @YES;
}else{
[self.goBackBtn setTitle:[NSString stringWithFormat:@"%d秒后可重新獲取", (int)number] forState:UIControlStateNormal];
return @NO;
}
}] takeUntilBlock:^BOOL(id _Nullable x) {
return number <= 0;
}];
self.goBackBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
number = kMaxLimitCount;
return timer;
}];
隨機(jī)數(shù)
1.獲取一個(gè)隨機(jī)整數(shù)范圍在:[0,10)包括0,不包括10
int a = arc4random() % 100;
2.獲取一個(gè)隨機(jī)數(shù)范圍在:[10,20],包括10,包括20
int b =10 + (arc4random() % 10);
轉(zhuǎn)------>生成不重復(fù)隨機(jī)數(shù)
思想:其原理就是利用兩個(gè)數(shù)組,第一個(gè)數(shù)組存放要隨機(jī)的原始數(shù)據(jù),第二個(gè)數(shù)組存放結(jié)果;然后arc4random產(chǎn)生一個(gè)隨機(jī)數(shù),將這個(gè)隨機(jī)數(shù)用作下標(biāo),把第一個(gè)數(shù)組對應(yīng)下標(biāo)的數(shù)據(jù)取出并刪除。取出后存入第二個(gè)數(shù)組。然后循環(huán)往復(fù)就可以了。即便兩次arc4random產(chǎn)生的隨機(jī)數(shù)是相同的,但第一個(gè)數(shù)組對應(yīng)下標(biāo)的數(shù)據(jù)卻是不一樣的 其實(shí)使用NSSet 也可以
兩個(gè)數(shù)組 code
-(NSArray *)randomArray
{
//隨機(jī)數(shù)從這里邊產(chǎn)生
NSMutableArray *startArray=[[NSMutableArray alloc] initWithObjects:@0,@1,@2,@3,@4,@5,@6,@7, nil nil];
//隨機(jī)數(shù)產(chǎn)生結(jié)果
NSMutableArray *resultArray=[[NSMutableArray alloc] initWithCapacity:0];
//隨機(jī)數(shù)個(gè)數(shù)
NSInteger m=8;
for (int i=0; i<m; i++) {
int t=arc4random()%startArray.count;
resultArray[i]=startArray[t];
startArray[t]=[startArray lastObject]; //為更好的亂序,故交換下位置
[startArray removeLastObject];
}
return resultArray;
}
** NSSet code**
NSArray *array = [[NSArray alloc] initWithObjects:@"A",@"B",@"C",@"D",@"E",nil];
NSMutableArray *randomArray = [[NSMutableArray alloc] init];
while ([randomArray count] < 3) {
int r = arc4random() % [array count];
[randomArray addObject:[array objectAtIndex:r]];
}
UILabel如何在XIB中換行
在Interface Builder中,選中要換行的UILabel,在屬性面板中,選中文本框,輸入第一行文字,預(yù)要換行時(shí),按住Optional(Alt)+Enter,自動(dòng)切換到第二行,(如果直接按enter鍵,則是確定輸入的內(nèi)容,不會(huì)自動(dòng)換行),同時(shí)別忘了將Lines屬性設(shè)置為0
關(guān)于tableView樣式為UITableViewStyleGrouped間距的設(shè)置
開始的時(shí)候,以為這樣寫就搞定了 如下
self.tableView.sectionHeaderHeight = 10;
self.tableView.sectionFooterHeight = 0;
發(fā)現(xiàn)發(fā)現(xiàn)section=0 的時(shí)候高度并沒有變化
最后發(fā)現(xiàn)self.tableView.sectionHeaderHeight = 10;可以不用設(shè)置,直接用代理的方法就可以,但是self.tableView.sectionFooterHeight = 0必須寫。 并且如果寫了self.tableView.sectionFooterHeight = 0之后,他的代理方法其實(shí)是不起作用的。簡單來說,就是只需實(shí)現(xiàn)下面的代碼
self.tableView.sectionFooterHeight = 0;
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 10;
}
上面的例子 是針對多個(gè)section的設(shè)置,如果只有一個(gè)section的話,就比較簡單了,直接設(shè)置tableHeadView就可以了
self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 10.f)];
或者修改tableView的內(nèi)邊距 contentInset
self.tableView.contentInset = UIEdgeInsetsMake(xxx, 0, 0, 0);
如果是調(diào)節(jié)section之間的距離,就一起調(diào)整兩個(gè)屬性,如果是整體上移,就調(diào)節(jié)內(nèi)邊距屬性contentInset
__weak 和__block的區(qū)別
__weak 本身可以解決循環(huán)引用,但是出了block作用域之后,就訪問不到這個(gè)對象了,可以在block里 聲明一個(gè)__strong 指向這個(gè)對象,這樣就可以使外部對象既能在 block 內(nèi)部保持住,又能避免循環(huán)引用的問題
__block 本身無法避免循環(huán)引用的問題,但是我們可以在 block 內(nèi)部手動(dòng)把 blockObj 賦值為 nil 的方式來避免循環(huán)引用的問題。另外一點(diǎn)就是 __block 修飾的變量在 block 內(nèi)外都是唯一的,要注意這個(gè)特性可能帶來的隱患
protocol里增加property
如果在protocol里定義了屬性,有兩種方法處理
- 就要在實(shí)現(xiàn)類里面自己實(shí)現(xiàn)get和set方法,
Student
遵守了協(xié)議,可以在Student
的實(shí)現(xiàn)文件里這樣操作
@synthesize yourProterry=_yourProterry;
- 在A的聲明文件里,重寫這個(gè)屬性 例如
in MyProtocal.h
@protocol MyProtocal <NSObject>
@property (nonatomic, copy) NSString *name;
@end
in Student.h
@interface Student : NSObject<MyProtocal>
@property (nonatomic, copy) NSString *name;
@end
其實(shí)protocol里增加property,主要是為了抽代碼,把公共的代碼抽出來,對于model而言,有一些共有的屬性,可以寫在協(xié)議里,有需要這些屬性的子model 直接遵守改協(xié)議即可,比較靈活。
使用webView 提交參數(shù)(提交表單時(shí))post方式
NSURL *url = [NSURL URLWithString: @"你的網(wǎng)址"];
NSString *body = [NSString stringWithFormat: @"參數(shù)1=%@&參數(shù)22=%@", @"val1",@"val2"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
[request setHTTPMethod: @"POST"];
[request setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
[webView loadRequest: request];
tips
連接參數(shù)時(shí)要用&
ARC下的assign和weak區(qū)別
The main difference between weak and assign is that the with weak, once the object being pointed to is no longer valid, the pointer is nilled out. Assigning the pointer the value nil avoids many crashes as messages sent to nil are essentially no-ops
Excerpt From: Daniel H Steinberg.
“Developing iOS 7 Apps for iPad and iPhone.” Dim Sum Thinking, Inc, 2014. iBooks. iTunes - Books
weak 比 assign 多了一個(gè)功能就是當(dāng)屬性所指向的對象消失的時(shí)候(也就是內(nèi)存引用計(jì)數(shù)為0)會(huì)自動(dòng)賦值為 nil ,這樣再向 weak 修飾的屬性發(fā)送消息就不會(huì)導(dǎo)致野指針操作crash。OC中向nil發(fā)消息,程序是不會(huì)崩潰的.
tips
在 ARC 模式下編程時(shí),指針變量一定要用 weak 修飾,只有基本數(shù)據(jù)類型和結(jié)構(gòu)體需要用 assgin ,例如 delegate ,一定要用 weak 修飾
__unsafe_unretained
:和__weak
一樣,唯一的區(qū)別便是,對象即使被銷毀,指針也不會(huì)自動(dòng)置空, 此時(shí)指針指向的是一個(gè)無用的野地址。如果使用此指針,程序會(huì)拋出 BAD_ACCESS 的異常。
理解__unsafe_unretained
__unsafe_unretained:和__weak 一樣,唯一的區(qū)別便是,對象即使被銷毀,指針也不會(huì)自動(dòng)置空, 此時(shí)指針指向的是一個(gè)無用的野地址。如果使用此指針,程序會(huì)拋出 BAD_ACCESS 的異常
examp1
id __unsafe_unretained obj = [[NSMutableArray alloc]init];
[obj addObject:@"obj"];
在第二條語句就會(huì)崩潰,分析:
附有__unsafe_unretained
修飾符的變量同附有__weak
修飾符的變量一樣,因?yàn)樽约荷刹⒊钟械膶ο蟛荒芾^續(xù)為自己持有,所以生成的對象會(huì)立即被釋放。也就是說在執(zhí)行完init方法以后,obj指針?biāo)赶虻膬?nèi)存就已經(jīng)釋放掉了,可是obj指針并沒有像附加__weak
的指針那樣,將指針自動(dòng)置為nil,它依然指向原來的地址,可是這塊地址的內(nèi)存已經(jīng)被系統(tǒng)回收了,再訪問就是非法的,也就是野指針,再執(zhí)行后面的addObject方法自然會(huì)出錯(cuò)了。
也就是說上面的代碼,把__unsafe_unretained
換成__weak
就不會(huì)崩潰,因?yàn)閛bj會(huì)自動(dòng)制置為nil。對nil發(fā)送消息是不會(huì)有問題的。
examp2
id __unsafe_unretained obj1 = nil;
{
id obj0 = [[NSMutableArray alloc]init];
[obj0 addObject:@"obj"];
obj1 = obj0;
NSLog(@"obj0 = %@", obj0);
}
NSLog(@"obj1 = %@", obj1);
依然在最后的NSLog語句崩潰。分析:
因?yàn)?code>__unsafe_unretained既不強(qiáng)引用,也不弱引用,作用域外obj0強(qiáng)引用失效,并且沒有其他指針強(qiáng)引用這個(gè)對象,所以自動(dòng)釋放持有的對象,obj1就相當(dāng)于野指針,訪問野指針就會(huì)崩潰;
也就是說,賦值給附有__unsafe_unretained
修飾符變量的對象在通過該變量使用時(shí),如果沒有確保其確實(shí)存在,那么應(yīng)用程序就會(huì)崩潰;
UIView transitionFromView 實(shí)現(xiàn)反復(fù)3D旋轉(zhuǎn)效果
效果如下
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion