系統會調用數組
duplicate symbol _OBJC_METACLASS_$_JKSerializer in: /Users/tony/Desktop/XXXProject/Lib/libMiPushSDK.a(JSONKit.o) /Users/tony/Library/Developer/Xcode/DerivedData/XXXProject-boqkajmzatzxohbyrrhklfiuknic/Build/Products/Debug-iphoneos/libPods.a(JSONKit.o) ld: 24 duplicate symbols for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
找到第三方庫安全
進行復制副本app
查看包信息iphone
`lipo -info libx.a` 針對多平臺須要逐一作解包重打包操做
建立臨時文件夾,用於存放armv7平臺解壓後的.o文件:mkdir armv7
ide
取出armv7平臺的包:lipo libx.a -thin armv7 -output armv7/libx-armv7.a
佈局
查看庫中所包含的文件列表:ar -t armv7/libx-armv7.a
ui
解壓出object file(即.o後綴文件):cd armv7 && ar xv libx-armv7.a
spa
找到衝突的包(JSONKit),刪除掉rm JSONKit.o
線程
從新打包object file:cd .. && ar rcs libx-armv7.a armv7/*.o
,能夠再次使用[2]中命令確認是否已成功將文件去除rest
將其餘幾個平臺(armv7s, i386)包逐一作上述[1-6]操做
從新合併爲fat file的.a文件:
`lipo -create libx-armv7.a libx-armv7s.a libx-i386.a -output libMiPushSDK-new.a`
拷貝到項目中覆蓋源文件:
`cp libMiPushSDK-new.a /Users/xxx/Desktop/XXXProject/Lib/libMiPushSDK.a`
這種問題主要出在cell 刷新次數頻繁的操做中,例如聊天界面接收與發送消息等操做
經過一個數組,先接收數據,而後再講此數組添加到數據源中,刷新界面
[self.collectionView performBatchUpdates:^{ //將臨時數組添加到數據源中 [self.messsagesSource addObjectsFromArray:_subMessageDataSource]; NSMutableArray *indexPaths = @[].mutableCopy; for (NSInteger i = _subMessageDataSource.count; i > 0 ; i--) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:(self.messsagesSource.count - i) inSection:0]; [indexPaths addObject:indexPath]; } [self.collectionView insertItemsAtIndexPaths:indexPaths]; } completion:^(BOOL finished) { if (finished) { [_subMessageDataSource removeAllObjects]; } }];
經過若引用來引用timer
__weak id weakSelf = self; timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
經過GCD 建立定時器
__weak typeof(self) weakSelf = self; double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [weakSelf doSomethingRepeatedly]; }); }
經過
- (void)timer2 { NSMethodSignature *method = [ViewController instanceMethodSignatureForSelector:@selector(invocationTimeRun:)]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:method]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES]; // 設置方法調用者 invocation.target = self; // 這裏的SEL須要和NSMethodSignature中的一致 invocation.selector = @selector(invocationTimeRun:); // 設置參數 // //這裏的Index要從2開始,覺得0跟1已經被佔據了,分別是self(target),selector(_cmd) // 若是有多個參數, 可依次設置3 4 5 ... [invocation setArgument:&timer atIndex:2]; [invocation invoke]; NSLog(@"start"); }
經過GCD 實現
實現延遲執行
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC); dispatch_after(delayTime, dispatch_get_main_queue(), ^(void){ NSLog(@"延遲2s後執行"); });
基於延遲執行實現
`void
dispatch_source_set_timer(dispatch_source_t source,
dispatch_time_t start,
uint64_t interval,
uint64_t leeway)` 主要是此方法
(void)gcdTimer1 {
// 獲取全局隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 建立定時器
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 開始時間
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
// dispatch_time_t start = dispatch_walltime(NULL, 0);
// 重複間隔
uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
// 設置定時器
dispatch_source_set_timer(_timer, start, interval, 0);
// 設置須要執行的事件
dispatch_source_set_event_handler(_timer, ^{
//在這裏執行事件 static NSInteger num = 0; NSLog(@"%ld", (long)num); num++; if (num > 4) { NSLog(@"end"); // 關閉定時器 dispatch_source_cancel(_timer); }
});
// 開啓定時器
dispatch_resume(_timer);
NSLog(@"start");
}
方式1: 經過監聽statusbar高度的變換,更新UI
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(layoutControllerSubViews) name:UIApplicationDidChangeStatusBarFrameNotification object:nil]; // 從新佈局 - (void)layoutControllerSubViews { // 對須要的UI從新適配Frame }
方法2: 在系統的viewDidLayoutSubviews
方法中從新設置值
-(void) viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.view.y = 0; self.view.height = ScreenHeght; }
self.definesPresentationContext = YES;
可能拍攝的照片與看到的照片是不一樣的
![來自簡書]()
//_cameraView爲相機視圖,即拍攝時看到圖片的區域 CGFloat scale = image.size.width / _cameraView.width;//計算出縮放的比例 CGFloat showImageH = image.size.height / scale;//縮放後圖片的高度 CGFloat offsetY = (showImageH - _cameraView.height) * 0.5;//上下超出的部分是相等的,因此*0.5得出上面超過的部分 CGRect rect = CGRectMake(x, y, width,height); CGImageRef tailorImageRef = CGImageCreateWithImageInRect(photo.CGImage, rect); UIImage *tailorImage = [UIImage imageWithCGImage:tailorImageRef];
能夠經過系統給定的屬性進行判斷
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { //iPhone, present activity view controller as is [self presentViewController:activityViewController animated:YES completion:nil]; } else { //iPad, present the view controller inside a popover if (![self.activityPopover isPopoverVisible]) { self.activityPopover = [[UIPopoverController alloc] initWithContentViewController:activityViewController]; [self.activityPopover presentPopoverFromBarButtonItem:self.shareItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } else { //Dismiss if the button is tapped while pop over is visible [self.activityPopover dismissPopoverAnimated:YES]; } }
iOS開發中 (Objective-C) 中,可變對象廣泛都是線程不安全的, 這樣在操做是就容易形成一些莫名其妙的問題出現 , 好比: UICollectionView的cell與數據源不一樣步啊等問題
//添加鎖機制 @synchronized(arrayM) { [arrayM addObject:profile]; } @synchronized(arrayM) { [arrayM removeObject:profile]; }
在開發中每每有時候須要往方法中傳入多個枚舉值,可是隻有一個參數, 須要經過__或運算__進行傳入,當須要獲取傳入的枚舉值時,須要經過__與運算__獲取
//或運算 int interestSet = SelectionKey.OP_READ | Selection.OP_WRITE; //與運算獲取值 boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;