Brother Han teaches you how to use iOS - Experience sharing

Brother Han teaches you how to use iOS - Experience sharing

[[148033]]

This article mainly explains 4 questions

  1. Load Magic

  2. AOP Aspect Oriented Programming

  3. NSNumber Or Int

  4. @() Adapt to 64-bit

1 Reduce the burden on appDelegate

After a long period of study, you finally mastered the iOS method. You found a job as an iOS developer and vowed to start your coding career. Your boss thinks highly of you and tells you that your skills are very tricky, so you should handle this project by yourself. Oh, this means that you will handle the entire project from start to finish, from the software architecture to the page display.

Using my half-baked papapa coding, I am determined to encapsulate the code well and write it beautifully (actually I heard from the experts about encapsulation, but I don’t really understand it)

The project is coming to an end. The boss tells you that our app will have a function of sharing to Moments in the future. Otherwise, how can we show the awesomeness of our product?

Then you heard that Umeng is better (it may be an advertisement). You went to Umeng to read their documentation and they told you to write this in the appdelegate didFinishLaunch method.

  1. ?[UMSocialData?setAppKey:@ "XX" ];
  2. ???? //?????Register on WeChat  
  3. ?[UMSocialWechatHandler?setWXAppId:@ "XXX" ??appSecret:@ "XX" ?url:@ "" ];
  4. ???? //????Register QQ  
  5. ?[UMSocialQQHandler?setQQWithAppId:@ "XXX" ?appKey:@ "XXX" ?url:@ "" ];

A few days later, my boss said we need to collect statistics on my page. You connected to Umeng's statistics and added another line of code in appdelegate didFinishLaunch.

The needs are endless. I need bug statistics (fir hud), user reminder rating system (iRate), push (jPush, pigeon push...)

Your determination to encapsulate the code perfectly and write it beautifully has long been defeated by your boss's demands.

Don't worry, Brother Han will teach you some tricks

Have you ever used smart libraries like IQKeyBoardManage and iRate?

Daniel's readme wrote this paragraph

  1. Key Features
  2. 1 ) CODELESS, Zero Line of Code No need to write any code
  3. 2 )?Works?Automatically? //Automatically works  
  4. 3 ) No More UIScrollView // No scrollview required  
  5. 4 ) No More Subclasses // No need to inherit the parent class  
  6. 5 ) No More Manual Work // No configuration required  
  7. 6 )?No?More?#imports? //No need to import  

In fact, it is not magical, it is just that the expert used the + load method

Anyone who studies OC knows that this code will be automatically called when a class is loaded into the runtime library. This is not the realization of automatic calling.

Write a class that inherits from NSObject

  1. # import ? @interface ?ThirdPartService?:?NSObject
  2. @end  
  3. ?# import ? "ThirdPartService.h"  
  4. ?# import ? "UMSocial.h"  
  5. ?# import ? "UMSocialWechatHandler.h"  
  6. ?# import ? "UMSocialQQHandler.h"  
  7. ?# import ??# import ? @implementation ?ThirdPartService
  8. ?+?( void )load?{
  9. static ?dispatch_once_t?onceToken;
  10. dispatch_once(&onceToken,?^{
  11. ??? //???TODO??Here is my own test??fir?hud  
  12. ????[FIR?handleCrashWithKey:@ "XX" ];
  13. ???? //????Friends Alliance  
  14. ????[UMSocialData?setAppKey:@ "XX" ];
  15. ???? //?????Hide platforms that are not installed  
  16. ????[UMSocialConfig?hiddenNotInstallPlatforms:@[UMShareToQQ,UMShareToQzone,UMShareToWechatSession,UMShareToWechatTimeline]];
  17. ???? //?????Register on WeChat  
  18. ????[UMSocialWechatHandler?setWXAppId:@ "XX" ?appSecret:@ "XX" ?url:@ "" ];
  19. ???? //????Register QQ  
  20. ???? //????TODO???QQ is not real  
  21. ????[UMSocialQQHandler?setQQWithAppId:@ "XX" ?appKey:@ "XX" ?url:@ "" ];
  22. ??? //???TODO????UM Statistics  
  23. ????[MobClick?startWithAppkey:@ "" ];
  24. ????[MobClick?setCrashReportEnabled:NO];
  25. ????NSLog(@ "Third-party service registration completed" );
  26. });
  27. }
  28. @end  

Similar to positioning, you can also write

Modules and services are completely separated

But some services such as APNS require LaunchOption, so they can only be written in appdDelegate. But in this way, a lot of code has been removed and only a few fixed ones are left. When you modify appDelegate later, it will feel very clear.

2 ViewController inheritance?

Next, we have connected to Umeng Statistics. The most basic thing about Umeng Statistics is the PV of the statistics page.

Umeng writes this way. For newbies, we think this is so easy.

I opened a certain vc (HomeViewController)

Wrote this in the code

  1. -( void )viewWillAppear:(BOOL)animated?{
  2. ???[ super ?viewWillAppear:animated];
  3. #ifndef?DEBUG
  4. ???[MobClick?beginLogPageView:NSStringFromClass([self? class ])];
  5. #endif
  6. }
  7. -( void )viewWillDisappear:(BOOL)animated?{
  8. ????[ super ?viewWillDisappear:animated];
  9. #ifndef?DEBUG
  10. ??[MobClick?endLogPageView:NSStringFromClass([self? class ])];
  11. #endif
  12. }

Then I may have dozens or even hundreds of pages in a project that need to count pv. I can't write this for every program.

We are smart and thought of inheritance

Such as MyBaseViewController:UIViewController

In this way, we need to do one thing: change all the classes in our project that inherit from UIViewController to inherit from MyBaseViewController. However, do you really think this is a good idea? We have dozens of controllers in a project, so I have to change each controller.

This kind of repetitive work is boring and prone to errors. You will miss a class when you copy it. The important thing is that many classes in our project are not directly inherited from UIViewController. Some may be UITableViewController, UICollectionViewContr0ller, UINavigationController, or even the less commonly used UISearchDisPlayController, UIPopoverController, and UIPresentController. Do you suddenly feel that there are so many?

This is not a trap. The trap is that in the future, when you become a big shot and hire a little brother, you tell him that all his classes must inherit from the various parent classes I wrote. Newbies always make mistakes without paying attention. Some classes forget to inherit, which makes it very difficult to check later and wastes time. Therefore, this design is unreasonable.

  • Brother Han will teach you the black magic Method swizzling again

What is this for? Baidu

Here is an article from NSHipster blogger

Chinese Translation

There is also an article explaining runtime.

practice

By using method intersection, we can intercept the attraction method. Here is the code.

This achieves the idea of ​​aspect-oriented programming (AOP)

On the code

  1. # import ? @interface ?UIViewController?(AOP)
  2. #warning??When running?Change the method?Do some aspect programming such as?Statistics?etc.
  3. ? @end  
  4. ?# import ? "UIViewController+AOP.h"  
  5. ?# import ?# import ?? @implementation ?UIViewController?(AOP)
  6. ?+?( void )load?{
  7. ??? static ?dispatch_once_t?onceToken;
  8. ??dispatch_once(&onceToken,?^{
  9. ????Class? class ?=?[self? class ];
  10. ???? //?When?swizzling?a?class?method,?use?the?following:  
  11. ???? //?Class?class?=?object_getClass((id)self);  
  12. ????swizzleMethod( class ,? @selector (viewDidLoad),? @selector (aop_viewDidLoad));
  13. ????swizzleMethod( class ,? @selector (viewDidAppear:),? @selector (aop_viewDidAppear:));
  14. ????swizzleMethod( class ,? @selector (viewWillAppear:),? @selector (aop_viewWillAppear:));
  15. ????swizzleMethod( class ,? @selector (viewWillDisappear:),? @selector (aop_viewWillDisappear:));
  16. });
  17. }
  18. ? void ?swizzleMethod(Class? class ,?SEL?originalSelector,?SEL?swizzledSelector)???{
  19. Method?originalMethod?=?class_getInstanceMethod( class ,?originalSelector);
  20. Method?swizzledMethod?=?class_getInstanceMethod( class ,?swizzledSelector);
  21. BOOL?didAddMethod?=
  22. class_addMethod( class ,
  23. ???????????????originalSelector,
  24. ???????????????method_getImplementation(swizzledMethod),
  25. ???????????????method_getTypeEncoding(swizzledMethod));
  26. if ?(didAddMethod)?{
  27. ????class_replaceMethod( class ,
  28. ??????????????????????swizzledSelector,
  29. ????????????????????????method_getImplementation(originalMethod),
  30. ????????????????????????method_getTypeEncoding(originalMethod));
  31. }? else ?{
  32. ????method_exchangeImplementations(originalMethod,?swizzledMethod);
  33. }
  34. ?}
  35. ?-?( void )aop_viewDidAppear:(BOOL)animated?{
  36. [self?aop_viewDidAppear:animated];
  37. }
  38. ?-( void )aop_viewWillAppear:(BOOL)animated?{
  39. [self?aop_viewWillAppear:animated];
  40. #ifndef?DEBUG
  41. ???[MobClick?beginLogPageView:NSStringFromClass([self? class ])];
  42. #endif
  43. }
  44. ?-( void )aop_viewWillDisappear:(BOOL)animated?{
  45. ????[self?aop_viewWillDisappear:animated];
  46. #ifndef?DEBUG
  47. ????[MobClick?endLogPageView:NSStringFromClass([self? class ])];
  48. #endif
  49. }
  50. ?-?( void )aop_viewDidLoad?{
  51. [self?aop_viewDidLoad];
  52. if ?([self?isKindOfClass:[UINavigationController? class ]])?{
  53. ????UINavigationController?*nav?=?(UINavigationController?*)self;
  54. ????nav.navigationBar.translucent?=?NO;
  55. ????nav.navigationBar.barTintColor?=?GLOBAL_NAVIGATION_BAR_TIN_COLOR;
  56. ????nav.navigationBar.tintColor?=?[UIColor?whiteColor];
  57. ????NSDictionary?*titleAtt?=?@{NSForegroundColorAttributeName:[UIColor?whiteColor]};
  58. ????[[UINavigationBar?appearance]?setTitleTextAttributes:titleAtt];
  59. ????[[UIBarButtonItem?appearance]
  60. ?????setBackButtonTitlePositionAdjustment:UIOffsetMake( 0 ,?- 60 )
  61. ?????forBarMetrics:UIBarMetricsDefault];
  62. }
  63. //????self.view.backgroundColor?=?[UIColor?whiteColor];  
  64. self.navigationController.interactivePopGestureRecognizer.delegate?=?(id)self;
  65. ?}
  66. ? @end  

A copy of the picture code is convenient for viewing

We have taken full advantage of black magic to achieve the benefits of aspect-oriented programming

The idea comes from here http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html

Black magic is not poison. Code written in accordance with a specification will not crash. As long as it can help us solve the problem, it is a good thing.

Black Magic performance has bottlenecks? You are still worried about bottlenecks even though it has reached the bottom of the runtime? Just use it with peace of mind? If you don't agree, you can use Time Profiel to test it.

Black magic is not omnipotent. For example, we need to encapsulate gestures in the navigation controller to uniformly manage the left return button. These things are better inherited.

Technology is a tool. Black cat, white cat, as long as it catches mice, it is a good cat.

#p#

3 Should network access parameters use basic data types or objects?

Let's look at two methods

  1. ?+?( void )getDataAtPageNo:(NSNumber?*)pageNo?PageSize:(NSNumber?*)pageSize?
  2. complete:(CompleteBlock)complete?{
  3. NSMutableDictionary?*param?=?[NSMutableDictionary?dictionary];
  4. ???? if ?(pageSize)?{
  5. ???????[param?setObject:pageSize?forKey:@ "pageSize" ];
  6. ???}
  7. ?[param?setObject:pageNo?forKey:@ "pageNo" ];
  8. //?SendRequest  
  9. }
  10. ?+?( void )getData2AtPageNo:( long ?)pageNo?PageSize:( long ?)pageSize?
  11. ?complete:(CompleteBlock)complete?{
  12. ?????NSMutableDictionary?*param?=?[NSMutableDictionary?dictionary];
  13. ???????[param?setObject:@(pageSize)?forKey:@ "pageSize" ];
  14. ???????[param?setObject:@(pageNo)?forKey:@ "pageNo" ];
  15. //?SendRequest  
  16. ?}

When accessing network requests, there are two main methods for designing a method for requests with parameters.

  1. Using objects as parameters

  2. Use basic data types as parameters

Normally this doesn't make a big difference, but Han Ge's suggestion is that basic data types should never appear.

In general, developers may think that there is no difference. Let me give you an example.

When designing a page to display data: The logic on the page is to load the first page by default, and the length of each page is 10 (the students on the server are generally very friendly, and the default length of each page is 10 if it is not passed). However, if it is passed, it will overwrite the default parameters written in the background. For example, if 20 is passed, the server will spit out 20 data

  1. In the first design scheme: A member variable of a PageNo PageSize object may be retained in a certain controller, and the corresponding parameters will be passed to the request method when pulling down to refresh or pulling up to load. If there is no special requirement, the pageSize object may be dispensable, that is, it may be nil, then there may be no such parameter in the corresponding param passed to the server.

    The server will return 20 pieces of data for a certain page to us.

  2. In the second design: A member variable of the basic data type PageNo pageSize may be retained in a controller, and handed over to the corresponding method when accessing the network request. Generally, we will not set a special value for PageSize unless there is a special requirement. However, the basic data type has a default value of 0 in traditional programming languages ​​such as OC and C. Although we have not assigned a value to pageSize, the default system defaults to an initial value of 0. When it is passed to the server, the default pageSize=10 written by the server will be overwritten. Such a request will neither report an error nor return data.

Super hard to debug

Therefore, in the network access, Han Ge's suggestion is that basic data types should never appear.

4 What are the benefits of using NSNumber over basic data types? 64-bit adaptation issues

We usually use it as a parameter cache for network requests or display it on the page

  1. For network request parameters, NSNumber is the best way because NSDictionary can only hold objects.
  2. Caching requires objects whether caching to plist or KeyArchive, so NSNumber is also very suitable.
  3. Display to page

I have seen friends assign values ​​to pages like this

We see that there seems to be nothing wrong with this

But we switch the device to iPhone5S or below, which is a 32-bit device

Note that there is a Warning

Why? Let's take a look at the header file of NSInteger

In 32-bit devices, it is Int; in 64-bit devices, it is Long

We all know that Apple does not allow apps that do not support 64-bit to be released, but it seems that we have never adapted for 32-bit and 64-bit.

In fact, the corresponding %d %zd %f placeholders in printf and NSLog are very strict. If you don't use them correctly, you will get unexpected results.

In fact, when we get an NSNumber, we don't know whether it is int, long, unsigned int, Bool, and directly converting to a certain type is risky. But Clang actually provides us with a very useful Macro @()

NSNumber is not a simple class. It is the implementation of a class cluster in Cocoa.

http://www.cocoachina.com/ios/20140109/7681.html

http://www.cocoachina.com/ios/20150106/10848.html

http://www.cocoachina.com/ios/20141218/10688.html

<<:  Do you know what features App development can really improve customer retention rate?

>>:  If the Internet and the economy really face a cold winter, I will give you a reassurance pill

Recommend

Before you read this, you definitely don’t understand what real ASO is.

As everyone knows, ASO refers to the search optim...

Why would Google open source its most important secrets?

Google's technology is one of the main drivin...

APP promotion: the details of Xiaomi promotion that you don’t know!

After Xiaomi became famous, the term "Weibo ...

18 details of Baidu's ocpc launch (Part 2)

Continuing from the previous article "18 det...

Live broadcast room operation strategy in 2022

Many friends who are in the live broadcast field ...

XY Apple Assistant: Three new iPhones of different sizes coming in autumn

iPhone 6s, as Apple's blockbuster product, wi...

Mosquito warning! I love people wearing these four colors the most

The picture material comes from the Internet Mosq...

3-step strategy to build a complete content operation framework

Content has always been an important system in th...

What is "ear water imbalance"? Is this disease serious?

The disease of "ear water imbalance" ha...