现在的位置: 首页 > 综合 > 正文

iPhone 一些小知识点总结

2013年12月05日 ⁄ 综合 ⁄ 共 12162字 ⁄ 字号 评论关闭
1,线程安全:  nonatomic代表其不是线程安全的,如果该变量是在UI中使用的,那么你就不用担心他了,因为所有的UI操作都是在主线程中进行的。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
2,堆与栈
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
ios所有的对象都是分配在堆上,所以我们应该用指针来访问他。
3,- (id)init 
{      self = [super init];  // call our super’s designated initializer
  if (self) { 
        // initialize our subclass here     }      return self;  } 
 
如果将self = [super init]; 改为 self = [self init]; 意思是:
Note that we call our own designated initializer on self, not super! We might add something to our designated initializer someday and we don’t  want to have to go back and change all
of our convenience initializers too. Only our designated initializer should call our super’s designated initializer.
我理解的意思为:我们在自己的构造器中构造自己,就是将以前构造的同时添加到这次构造,不用在调用父类的构造器
4,if(self=[super init])为什么不用“==”而用“=”:
这里不是判断self与[super init]是否相等,而是判断是否可以成功初始化。 [super init]:父类初始化成功的话,通过=给self,这样self成为一个非空对象,整个来说即非false(非NO)。 于是也就变成了: if ( !false ){ //成功初始化后执行的代码 }   如果init失败 self则为空 if条件为假 于是if段内语句不执行
5,SEL的常用方法
SEL shootSelector = @selector(shoot); 
if ([obj respondsToSelector:@selector(shoot)]) {      [obj shoot];  }
如果你有一个SEL,你可以让一个对象来实现他,用performSelector: or performSelector:withObject: 方法
[obj performSelector:shootSelector];  [obj performSelector:shootAtSelector withObject:coordinate]; 
 在NSArray中使用: [array makeObjectsPerformSelector:shootSelector]; // cool, huh? [array makeObjectsPerformSelector:shootAtSelector withObject:target]; // target is an id
在UIButton中使用:[button addTarget:self action:@selector(digitPressed:) ...]; 
6,轻量级的存储是NSUserDefaults
[[NSUserDefaults standardUserDefaults] setArray:rvArray forKey:@“RecentlyViewed”]; 
一些常用方法:
- (void)setDouble:(double)aDouble forKey:(NSString *)key;  - (NSInteger)integerForKey:(NSString *)key;  // NSInteger 是一个 32 or 64 位的int - (void)setObject:(id)obj forKey:(NSString *)key;
// obj 必须是一个 Property List - (NSArray *)arrayForKey:(NSString *)key; //如果这个key所对应的value不是NSArray的话,将返回空 在每次对 
NSUserDefaults进行更改后,千万不要忘记更新
[[NSUserDefaults standardUserDefaults] synchronize]; 

7,

1》自定义UIView,重写该方法即可:- (void)drawRect:(CGRect)aRect; 

UIView会自动调用该方法,千万不可以显示调用!
想要提醒程序重新进行UIView的绘制,可调用:
- (void)setNeedsDisplay; 
- (void)setNeedsDisplayInRect:(CGRect)aRect; 

那么在drawRect函数中做什么呢?

首先获得绘画的内容:CGContextRef context = UIGraphicsGetCurrentContext(); 
2》例:画一条绿色的直线的完整代码
开始画线
CGContextBeginPath(context);
具体操作:
CGContextMoveToPoint(context, 75, 10);
CGContextAddLineToPoint(context, 160, 150);
CGContextAddLineToPoint(context, 10, 150);
CGContextDrawPath(context, kCGPathFillStroke);  // kCGPathFillStroke is a constant
[[UIColor greenColor] setFill];   // object-oriented convenience method (more in a moment)
[[UIColor redColor] setStroke]; 
结束画线(并不是一定需要的)
CGContextClosePath(context);   // not strictly required
3》如果你想重新拥有一个绘画内容,你可以将原来的推出,使用新创建的
- (void)drawGreenCircle:(CGContextRef)ctxt { 
    UIGraphicsPushContext(ctxt); 
    [[UIColor greenColor] setFill]; 
     // draw my circle
    UIGraphicsPopContext(); 
}
4》像UILabel,UIImageview也都可以用CGContext实现在屏幕上:
      用当前CGContext创建一个uiimage:
UIGraphicsBeginImageContext(CGSize); 
// draw with CGContext functions
UIImage *myImage = UIGraphicsGetImageFromCurrentContext(); 
UIGraphicsEndImageContext(); 

      uilabel:NSString *text = @“some”; 
[text drawAtPoint:(CGPoint)p withFont:theFont];  // NSString instance method
画的时候,一个字符需要多大的空间
CGSize textSize = [text sizeWithFont:myFont];    // NSString instance method
5》你也可以从一个UIImage获得他的RepresentationData
NSData *jpgData = UIImageJPEGRepresentation((UIImage *)myImage, (CGFloat)quality); 
NSData *pngData = UIImagePNGRepresentation((UIImage *)myImage); 
8,持久存储的五种方法:
1》Property Lists
用 writeToURL:atomically: 和initWithContentsOfURL: in NSArray or NSDictionary
或者在适当的时候使用 NSUserDefaults .
可以使用NSPropertyListSerialization 将Property Lists 转换为NSData.
2》Archiving Objects 序列化和反序列化文档
该类需实现NSCodeing接口,以及以下两个方法
- (void)encodeWithCoder:(NSCoder *)coder; 
- initWithCoder:(NSCoder *)coder; 
其他类中调用:
+ (NSData *)archivedDataWithRootObject:(id <NSCoder>)rootObject; 
+ (id <NSCoder>)unarchiveObjectWithData:(NSData *)data; 
下面这段代码实现对象的深度复制:
id <NSCoder> object = ...; 
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object]; 
id <NSCoder> dup = [NSKeyedArchiver unarchiveObjectWithData:data]; 

3》Storing things in the Filesystem 将数据保存在文件系统即沙盒中
NSFileManager为线程安全的
使用NSFileManager的方法:- (NSArray *)URLsForDirectory:(NSSearchPathDirectory)directory     // see below
                    inDomains:(NSSearchPathDomainMask)domainMask;  // NSUserDomainMask
4》SQLite 数据库常用的方法:
int sqlite3_open(const char *filename, sqlite3 **db);  // get a database into db
int sqlite3_exec(sqlite3 *db,                          // execute SQL statements
                 const char *sql, 
                 int (*callback)(void *, int, char **, char **), 
                 void *context, 
                 char **error); 
int mycallback(void *context, int count, char **values, char **cols);  // data returned
int sqlite3_close(sqlite3 *db);                        // close the database
5》Core Data 关系数据库 使用NSManagedObjectContext进行管理
1我们可以在创建项目时勾选:Use Core Data,程序会自动创建一个NSManagedObjectContext
2 创建一个 UIManagedDocument 对 managedObjectContext (a @property).做出请求
UIManagedDocument *document = [[UIManagedDocument] initWithFileURL:(URL *)url]; 
在你使用之前必须打开它,首先验证其是否存在: [[NSFileManager defaultManager] fileExistsAtPath:[url path]] 
如果是,就打开它
- (void)openWithCompletionHandler:(void (^)(BOOL success))completionHandler; 
如果不是,就创建它
- (void)saveToURL:(NSURL *)url 
 forSaveOperation:(UIDocumentSaveOperation)operation 
 competionHandler:(void (^)(BOOL success))completionHandler; 

例子:

Example self.document = [[UIManagedDocument] initWithFileURL :( URL *)url]; if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) { [document openWithCompletionHandler:^(BOOL success) { if (success) [self documentIsReady]; if (!success) NSLog(@“couldnt open document at %@”, url); }]; } else { [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { if (success) [self documentIsReady]; if (!success) NSLog(@“couldnt create document at %@”, url); }]; }

3在开始使用之前,必须检查它的状态:

- (void)documentIsReady 

    if (self.document.documentState == UIDocumentStateNormal) { 
        NSManagedObjectContext *context = self.document.managedObjectContext; 
        // do something with the Core Data context
    } 
} 其他类型的状态有:
UIDocumentStateClosed 文件未打开,或已经不存在
UIDocumentStateSavingError 保存失败
UIDocumentStateEditingDisabled (temporarily unless failed to revert to saved)
UIDocumentStateInConflict 其他程序也在使用它,造成冲突
4获得NSManagedObject NSManagedObject 不是线程安全的,我们可以向数据库中插入对象
NSManagedObject *photo = 
   [NSEntityDescription insertNewObjectForEntityForName:@“Photo” 
                                 inManagedObjectContext:(NSManagedObjectContext *)context]; 
我们也可以获得对象的属性:NSKeyValueObserving 
- (id)valueForKey:(NSString *)key; 
- (void)setValue:(id)value forKey:(NSString *)key; 
5 PS:可以使用XCode创建NSManagedObject的子类来管理这些属性
其中的@dynamic的意义是:
该变量没有实现他的getter和setter方法,但是如果向该变量发送消息,他会在Objective-C 运行时实现。
It says “I do not implement the setter or getter for this 
property, but send me the message anyway and I’ll use the 
Objective-C runtime to ?gure out what to do.”
There is a mechanism in the Objective-C runtime to “trap” 
a message sent to you that you don’t implement.
之后即可使用点来访问这些属性:
photo.thumbnailData = [FlickrFetcher urlForPhoto:photoDictionary format:FlickrPhotoFormat...]; 
photo.whoTook = ...; // a Photographer object we created or got by querying
photo.whoTook.name = @“CS193p Instructor”; // yes, multiple dots will follow relationships
6NSFetchRequest 的使用:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@“Photo”]; 
request.fetchBatchSize = 20; 
request.fetchLimit = 100; 
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 
request.predicate = ...; 
9,NSNotification
获得通知管理中心的实例: [NSNotificationCenter defaultCenter]
然后添加观察者:

- (void)addObserver :( id)observer // you (the object to get noti?ed) selector :( SEL)methodToSendIfSomethingHappens name :( NSString *)name // what you’re observing (a constant somewhere) object :( id)sender; // whose changes you’re interested in (nil is anyone’s)

当通知被触发时,调用该函数:

- (void)methodToSendIfSomethingHappens :( NSNotification *)notification { notification.name // the name passed above notification.object // the object sending you the noti?cation notification.userInfo // noti?cation-speci?c information about what happened }

在使用完之后,千万记得remove

[center removeObserver:self]; 或者使用
[center removeObserver:self name:UIDocumentStateChangedNotification object:self.document]; 
例子:当一个core data 改变时的通知

- (void)viewDidAppear :( BOOL)animated { [super viewDidAppear:animated]; [center addObserver:self selector:@selector(contextChanged :) name:NSManagedObjectContextObjectsDidChangeNotification object:self.document.managedObjectContext]; } - (void)viewWillDisappear :( BOOL)animated { [center removeObserver:self name:NSManagedObjectContextObjectsDidChangeNotification object:self.document.managedObjectContext]; [super viewWillDisappear:animated]; }

- (void)contextChanged :( NSNotification *)notification { The notification.userInfo object is an NSDictionary with the following keys: NSInsertedObjectsKey // an array of objects which were inserted NSUpdatedObjectsKey // an array of objects whose attributes changed NSDeletedObjectsKey // an array of objects which were deleted }

10,分类的一些特性:

他没有自己的实例变量,并且不能用@synthesize 在他的实现里。
11,NSPredicate 谓词的使用
NSString *serverName = @“flickr-5”; 
NSPredicate *predicate =  
 [NSPredicate predicateWithFormat:@“thumbnailURL contains %@”, serverName]; 
NSCompoundPredicate 组合谓词:
NSArray *array = [NSArray arrayWithObjects:predicate1, predicate2, nil]; 
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:array]; 

11,UITabbarController的tabBarItem

iPhone 一些小知识点总结 - 好好 - 奋斗的历程
- (void)somethingHappenedToCauseUsToNeedToShowABadgeValue

{
   self.tabBarItem.badgeValue = @“R”;
}

 12,[pool drain] 和 [pool release] 的区别:

release,在引用计数环境下,由于NSAutoReleasePool是一个不可以被retain的类型,所以release会直接dealloc pool对象。当pool被dealloc的时候,pool向所有在pool中的对象发出一个release的消息,如果一个对象在这个pool中autorelease了多次,pool对这个对象的每一次autorelease都会release。在GC环境下release是一个no-op操作(代表没有操作,是一个占据进行很少的空间但是指出没有操作的计算机指令)。

drain,在引用计数环境下,它的行为和release是一样的。在GC的环境下,这个方法调用objc_collect_if_needed出发GC。

因此,重点是:在GC环境下,release是一个no-op,所以除非你不希望在GC环境下出发GC,你都应该使用drain而不是使用release来释放pool。

13,OpenGL的一些基础:

《一》OpenGL是开放的图形库,仅仅是用于显示2维和3维的图形。OpenGL ES是OpenGL的子集。
编程包括四个步骤:(建立一个基于OpenGL的应用程序
1.定义模型
2.定义视角
3.建立OpenGL的状态
4.绘制几何图形:首先绘制形状:考虑你的模型----将你的模型转换为 能识别的几何图形-----激活客户状态---定义顶点数组---绘制数组----三角形化的点,然后使形状变形:矩阵---变形操作堆栈----压入/弹出变形操作----暗示3个不同的空间----推荐场景图或者父/子结构---局部空间---全体空间----父/子空间
《二》使用PVR贴图来提高性能和效率:
将你的资源(png, jpg)转换为PVR格式:使用终端进行转换:

In /Developer/Platforms/iPhoneOS.platform/usr/bin ./texturetool -e PVRTC -o output/myImage.pvr input/myImage.jpg


使用OpenGL方法载入PVR,使用Texture2D类载入:

- (id) initWithData :( const void*)data pixelFormat :( Texture2DPixelFormat)format pixelsWide :( NSUInteger)width pixelsHigh :( NSUInteger)height contentSize :( CGSize)size;

绘制贴图:激活状态---载入贴图---贴图坐标----像素格式---大小
14,《一》NSThead的基础:
每个线程自动生成一个Run loop实例
每个 需要生成一个自己的autorelease 池
提供了方便的方法来在线程间传递信息

// 发射一个新的线程 [NSThread detachNewThreadSelector:@selector(doWork :) withTarget:self object:someData]; // 将信息送回主线程 [self performSelectorOnMainThread:@selector(allDone :) withObject:[someData result] waitUntilDone:NO];

《二》线程的缺点: 可能会引入暗含的,无法断定的 bugs    代码可能会更难维持
最坏的情况是,更多的线程可能意味着更慢的代码
《三》NSOperation  :抽象的父类        管理线程的生成和生命周期         封装一个单元的工作到一个对象里        指定优先级和依赖性
NSOperationQueue:
通常通过加入一个队列来计划操作的运行          选择一个可以同时运行的操作的最大数               队列根据优先级和依赖性来运行操作

15,Locks的相关: NSLock 保护代码的重要部分,协调访问共享数据

- (void)someMethod
{
[myLock lock];
// 
[myLock unlock]
}
NSLock的风险:很难正确的锁定!只要有一个客户的行为非常糟糕 在lock之外访问共享数据   死锁  优先级倒转
16,使用LLVM/Clang 发现Bug:
静态分析C/Objective-C 代码的工具
识别可能的bugs:泄漏        使用了未经初始化或者已经释放的变量              没有dealloc方法
LLVM/Clang static analyzer自动帮助检测Objective-C程序中的bug。它是一款非常棒的用于发现内存泄漏和其他问题的工具。从Xcode 3.2开始,可以直接从Xcode中运行该分析器。选择Build(构建)→Build and Analyze(构建并分析)(Command-Shift-A)
17,切换视图控制器
[self presentModalViewController:viewController animated:YES];
[self dismissModalViewControllerAnimated:YES];
18,直接使用XIB文件创建一个View
    UIView *view=[[[NSBundle mainBundle] loadNibNamed:@"RootVC_TblCell" owner:nil options:nil] objectAtIndex:0];
    UIView *navBar=[[[NSBundle mainBundle] loadNibNamed:@"RootVCNavigationBar"  owner:nil  options:nil] objectAtIndex:0]; 
19,当使用UITableView时,想实现自定义的cell可以,重写cell的subviews。也可自定义一个view,直接将其添加到cell上,可根据view的tag,来返回所需要的view的组件:
 static NSString *const cell_ID=@"cell_ID"; 
 UITableViewCell *cell=(UITableViewCell *)[atableView dequeueReusableCellWithIdentifier:cell_ID];
   GoodImageView *goodsImage=nil;
    UILabel *titleLbl=nil;
  if (cell==nil) {
       cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_ID];
      UIView *view=[[[NSBundle mainBundle] loadNibNamed:@"RootVC_TblCell" owner:nil options:nil] objectAtIndex:0];
 [cell addSubview:view];
titleLbl=(UILabel *)[cell viewWithTag:TitleLblTag]; 

抱歉!评论已关闭.