Developer experience of iOS traps(Updating)

Traps about WKWebView

When memory is not enough, WKWebView will disappear white screen.

  • WKWebView is a multi process component, WebContent Process will be crashed. At the same time, WKWebView.URL will be nil. To use below function to reload webview.
    - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)){
        [self.webView reload];
    }
    複製代碼

Intercept JS request in NSURLProcotol, it will cause post-request lost thier request-body and request-bodystream.

  • It took me several days to solve this problem. To the end, I use intercept ajax to get the post-body and post-bodystream, when the post-request launch again, set twice element to renew a newer post-request.

WKWebView cookie lost is the same question about "lost request-body".


Apdating H5 pages to mobile terminals from WKWebView


WKWebView intercept redirection method execution order

// step 1
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;

//step 2
- (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation;

// step 3
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;

// step 4
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;

// step 5
- (void)startLoading;

// step 6
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

複製代碼

Customized UIView

Using -(void)reloadData;to selected or unselected TableViewCell to refresh the didslected-cell will appear cell-list flashing.

  • Sign the previous-cell and didselected-cell with two mark, and use reloadSection:withRowAnimation: or reloadRow:withRowAnimation: to refresh relateive cell.

Refresh TableViewCell or CollectionViewCell,system will add an implicit fade animation by default.

  • To remove the default animation, it's three method to solve.
//First function
[UIView performWithoutAnimation:^{
    [collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]];
}];
//Second function
[UIView animateWithDuration:0 animations:^{
    [collectionView performBatchUpdates:^{
        [collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]];
    } completion:nil];
}];
//Three function
[UIView setAnimationsEnabled:NO];
    [self.trackPanel performBatchUpdates:^{
        [collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]];
    } completion:^(BOOL finished) {
        [UIView setAnimationsEnabled:YES];
}];
複製代碼

drawRect

  • When drawRect

iOS Underlying principle

An object inhert NSObject occupy how many memory?

  • iOS system distrubution 16 byte to an object, but there is only 8 bytes in the implementation of NSObject.

Animation

What problem will cause by offscreen-rendered?

  • offscreen-rendered will create a render outside GPU, cost CUP performance. such as shouldRasterize、masks、shadows、edge antialiasing、group opacity、cornerRadius、gradual change. Pay Attention to, after iOS9.0 UIImageView will not cause offscreen-rendered.

Face to Aspect Oriented Programming (AOP)

AOP compare the advantages of OOP?

  • OOP is horizontal divides the system into many modules, such as IM、Friends、Me. And these modules will generate many sub modules. AOP is vertical devides the system, extract the common parts of each moudule.

How to use AOP in project?

Due to iOS examine

How to solve the refuse of Appstore, including machine trail and person trail?

  • Check the permissions of app are all set in info.plist. such as camera, stroge, location, microphone, photo library.
  • App introduction page should be Apple style, remember not to use andriod style.

What's a rigorous singleton ?

  • alloc-init,dispatch_once_t onceToken,copy,mutableCopy,these four function should create the same memory address.

Data Structure and Algorithm

Objective-C and Swift

@Property

  • @property = ivar + getter + setter, is combination of instance variables and setter/getter method.html

  • Keywords about property: atomic and nonatomic, assign, strong, copy, weak, unsafe_unretained.ios

    • atomic - nonatomic:Compare with atomic, nonatomic is faster.Because it's faster, it cause unsafer relatively. If want to make sure the thread safe, atomic is unreliable, you should use synchrolock. such as,
      // synchrolock, to be thread safe
      - (void)setSomeString:(NSString *)someString {
          @synchronized(self) {
              _someString = someString;
          }
      }
      //concurrent queue
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      - (NSString *)someString {
          __block NSString *localSomeString;
          dispatch_sync(_queue, ^{
              localSomeString = _someString;
          });
          return localSomeString;
          }
      複製代碼

    The ideal solution is, Getter function realized by dispatch_sync(dispatch_queue_t queue, dispatch_block_t blcok);, And setter function realized by dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t blcok);web

    • assign:
    • strong:
    • copy:
    • weak:
    • unsafe_unretained:

    link to 重識iOS之Propertyajax


Reflection mechanism of Objective-C

Block

What's the essence of block?
How much tpyes of block? How do block come into being?
Why can __block modified variables change their value in block?

Communication between threads

interviewobjective-c

More about GCD

dispatch_queue_t
dispatch_block_t
複製代碼
// GCD 用同步方法執行任務
dispatch_sync(dispatch_queue_t queue, dispatch_block_t blcok);

// GCD 用異步方法執行任務
dispatch_async(dispatch_queue_t queue, dispatch_block_t blcok);
複製代碼
  • sync:Only run in current thread, couldn't create thread.
  • async:Excute in new thread, can create new thread.
dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t blcok);

dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t blcok);
複製代碼
  • dispatch_barrier_sync:Upload a barrier should wait for pervious barrier excuted, then excute the barrier. It's excute in main thread.
  • dispatch_barrier_async:Upload a barrier excute in async, and it will excute if you upload immediately.

------- Example below -------shell

//concurrent queue Barrier
- (void)concurrentQueue2Barrier
{
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 0 %d",i);
        }];
    });
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 1 %d",i);
        }];
    });
    NSLog(@"Sync barrier start😊");
    dispatch_barrier_sync(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Sync barrier, %@",[NSThread currentThread]);
        }];
    });
    NSLog(@"Sync barrier end😊");
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 2 %d",i);
        }];
    });
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 3 %d",i);
        }];
    });
    NSLog(@"ASync barrier start 😄");
    dispatch_barrier_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"ASync barrier %@",[NSThread currentThread]);
        }];
    });
    NSLog(@"ASync barrier end 😄");
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 4 %d",i);
        }];
    });
    dispatch_async(concurrentQueue, ^{
        [self forNumIncrementCondition:5 actionBlock:^(int i) {
            NSLog(@"Task 5 %d",i);
        }];
    });
}
 
 
- (void)forNumIncrementCondition:(NSUInteger )num  actionBlock:(void(^)(int i))actionBlcok
{
    for (int a = 0; a < num; a ++)
    {
        if (actionBlcok) {
            actionBlcok(a);
        }
    }
}

<!--Barrier[5141:1319243] Sync Barrier start😊-->
<!--Barrier[5141:1319371] Task0 0-->
<!--Barrier[5141:1322592] Task1 0-->
<!--Barrier[5141:1319371] Task0 1-->
<!--Barrier[5141:1322592] Task1 1-->
<!--Barrier[5141:1319371] Task0 2-->
<!--Barrier[5141:1322592] Task1 2-->
<!--Barrier[5141:1319371] Task0 3-->
<!--Barrier[5141:1322592] Task1 3-->
<!--Barrier[5141:1319371] Task0 4-->
<!--Barrier[5141:1322592] Task1 4-->
<!--Barrier[5141:1319243] Sync Barrier, <NSThread: 0x60800006f300>{number = 1, name = main}-->
<!--Barrier[5141:1319243] Sync Barrier, <NSThread: 0x60800006f300>{number = 1, name = main}-->
<!--Barrier[5141:1319243] Sync Barrier, <NSThread: 0x60800006f300>{number = 1, name = main}-->
<!--Barrier[5141:1319243] Sync Barrier, <NSThread: 0x60800006f300>{number = 1, name = main}-->
<!--Barrier[5141:1319243] Sync Barrier, <NSThread: 0x60800006f300>{number = 1, name = main}-->
<!--Barrier[5141:1319243] Sync Barrier end😊-->
<!--Barrier[5141:1319243] ASync Barrier start 😄-->
<!--Barrier[5141:1319371] Task3 0-->
<!--Barrier[5141:1322592] Task2 0-->
<!--Barrier[5141:1319243] ASync Barrier end 😄-->
<!--Barrier[5141:1319371] Task3 1-->
<!--Barrier[5141:1322592] Task2 1-->
<!--Barrier[5141:1319371] Task3 2-->
<!--Barrier[5141:1322592] Task2 2-->
<!--Barrier[5141:1319371] Task3 3-->
<!--Barrier[5141:1322592] Task2 3-->
<!--Barrier[5141:1319371] Task3 4-->
<!--Barrier[5141:1322592] Task2 4-->
<!--Barrier[5141:1322592] ASync Barrier <NSThread: 0x60c00046dbc0>{number = 5, name = (null)}-->
<!--Barrier[5141:1322592] ASync Barrier <NSThread: 0x60c00046dbc0>{number = 5, name = (null)}-->
<!--Barrier[5141:1322592] ASync Barrier <NSThread: 0x60c00046dbc0>{number = 5, name = (null)}-->
<!--Barrier[5141:1322592] ASync Barrier <NSThread: 0x60c00046dbc0>{number = 5, name = (null)}-->
<!--Barrier[5141:1322592] ASync Barrier <NSThread: 0x60c00046dbc0>{number = 5, name = (null)}-->
<!--Barrier[5141:1322592] Task4 0-->
<!--Barrier[5141:1319371] Task5 0-->
<!--Barrier[5141:1322592] Task4 1-->
<!--Barrier[5141:1319371] Task5 1-->
<!--Barrier[5141:1322592] Task4 2-->
<!--Barrier[5141:1319371] Task5 2-->
<!--Barrier[5141:1322592] Task4 3-->
<!--Barrier[5141:1319371] Task5 3-->
<!--Barrier[5141:1322592] Task4 4-->
<!--Barrier[5141:1319371] Task5 4-->

複製代碼

iOS Reverse

  • frida-ios-dump:break shell, to have decode file.
相關文章
相關標籤/搜索