iOS develop note

  • facebook-wda can use python to call wda, which can be used to simulate user's simulation on iPhone.

  • iproxy can be used to re-track iphone's message to local by

 iproxy <local port> <remote port> [udid]
  • All animation should run on main thread.

  • When animation by changing UINSLayoutConstraint, [[animatingView parentView] layoutIfNeeded] should be called before animation and in the animation block.

  • To call the inner method of UIButton's UIImageView to make animation( such as image transition), you have to make UIImageView not NULL at first.

  • iCloud and iTunes do not back up the contents of the following directories:

<Application_Home>/AppName.app
<Application_Data>/Library/Caches
<Application_Data>/tmp
  • When a user downloads an app update, iTunes installs the update in a new app directory. It then moves the user’s data files from the old installation over to the new app directory before deleting the old installation. Files in the following directories are guaranteed to be preserved during the update process:
*<Application_Data>*/Documents
*<Application_Data>*/Library
  • [UIImage imageNamed:@"imageName"] will cache the image
    [UIImage imageWithContentOfFile:@fullPath"] simply load the image and no cache.

  • Optimize codes: using

[myView.layer setShadowPath:[[UIBezierPath bezierPathWithRect:myView.bounds] CGPath]];

rather than

[myView.layer setShadowOpacity:0.5]

to draw shadow.
refer to https://markpospesel.wordpress.com/2012/04/03/on-the-importance-of-setting-shadowpath/

  • Offscreen drawing on the other hand refers to the process of generating bitmap graphics in the background using the CPU before handing them off to the GPU for onscreen rendering. In iOS, offscreen drawing occurs automatically in any of the following cases:
    Core Graphics (any class prefixed with CG)
    The drawRect() method, even with an empty implementation.
    CALayers with a shouldRasterize property set to YES.
    CALayers using masks (setMasksToBounds) and dynamic shadows (setShadow
    ).
    Any text displayed on screen, including Core Text. Group opacity (UIViewGroupOpacity).

refer to https://robots.thoughtbot.com/designing-for-ios-graphics-performance

  • When you call endUpdate
    the number returned from tableView:numberOfRowsInSection: must be the same as the number at beginUpdate minus the number of rows deleted.

  • In tableView beginUpdates block, it defers any insertions of rows or sections until after it has handled the deletions of rows or sections.

  1. About "performSelector may cause a leak because its selector is unknown"

SolutionThe compiler is warning about this for a reason. It's very rare that this warning should simply be ignored, and it's easy to work around. Here's how:

if (!_controller) {
  return; 
}
SEL selector = NSSelectorFromString(@"someMethod");
IMP imp = [_controller methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;func(_controller, selector);

Or more tersely (though hard to read & without the guard):

SEL selector = NSSelectorFromString(@"someMethod");
((void (*)(id, SEL))[_controller methodForSelector:selector])(_controller, selector);

Explanation
What's going on here is you're asking the controller for the C function pointer for the method corresponding to the controller. All NSObjects respond to methodForSelector:, but you can also use class_getMethodImplementation in the Objective-C runtime (useful if you only have a protocol reference, like id<SomeProto>). These function pointers are called IMPs, and are simple typedefed function pointers (id (*IMP)(id, SEL, ...))1. This may be close to the actual method signature of the method, but will not always match exactly.

Once you have the IMP, you need to cast it to a function pointer that includes all of the details that ARC needs (including the two implicit hidden arguments self and _cmd of every Objective-C method call). This is handled in the third line (the (void *) on the right hand side simply tells the compiler that you know what you're doing and not to generate a warning since the pointer types don't match).

Finally, you call the function pointer2.

Complex Example
When the selector takes arguments or returns a value, you'll have to change things a bit:

SEL selector = NSSelectorFromString(@"processRegion:ofView:");
IMP imp = [_controller methodForSelector:selector];
CGRect (*func)(id, SEL, CGRect, UIView *) = (void *)imp;
CGRect result = _controller ? func(_controller, selector, someRect, someView) : CGRectZero;

Reasoning for Warning
The reason for this warning is that with ARC, the runtime needs to know what to do with the result of the method you're calling. The result could be anything: void, int, char, NSString *, id, etc. ARC normally gets this information from the header of the object type you're working with.3
There are really only 4 things that ARC would consider for the return value:4

Ignore non-object types (void, int, etc)
Retain object value, then release when it is no longer used (standard assumption)Release new object values when no longer used (methods in the init/ copy family or attributed with ns_returns_retained)
Do nothing & assume returned object value will be valid in local scope (until inner most release pool is drained, attributed with ns_returns_autoreleased)
The call to methodForSelector: assumes that the return value of the method it's calling is an object, but does not retain/release it. So you could end up creating a leak if your object is supposed to be released as in #3 above (that is, the method you're calling returns a new object).

For selectors you're trying to call that return void or other non-objects, you could enable compiler features to ignore the warning, but it may be dangerous. I've seen Clang go through a few iterations of how it handles return values that aren't assigned to local variables. There's no reason that with ARC enabled that it can't retain and release the object value that's returned from methodForSelector: even though you don't want to use it. From the compiler's perspective, it is an object after all. That means that if the method you're calling, someMethod, is returning a non object (including void), you could end up with a garbage pointer value being retained/released and crash.

Additional Arguments
One consideration is that this is the same warning will occur with performSelector:withObject: and you could run into similar problems with not declaring how that method consumes parameters. ARC allows for declaring consumed parameters, and if the method consumes the parameter, you'll probably eventually send a message to a zombie and crash. There are ways to work around this with bridged casting, but really it'd be better to simply use the IMP and function pointer methodology above. Since consumed parameters are rarely an issue, this isn't likely to come up.

Static Selectors
Interestingly, the compiler will not complain about selectors declared statically:

[_controller performSelector:@selector(someMethod)];

The reason for this is because the compiler actually is able to record all of the information about the selector and the object during compilation. It doesn't need to make any assumptions about anything. (I checked this a year a so ago by looking at the source, but don't have a reference right now.)SuppressionIn trying to think of a situation where suppression of this warning would be necessary and good code design, I'm coming up blank. Someone please share if they have had an experience where silencing this warning was necessary (and the above doesn't handle things properly).

More
It's possible to build up an NSMethodInvocation to handle this as well, but doing so requires a lot more typing and is also slower, so there's little reason to do it.

History
When the performSelector: family of methods was first added to Objective-C, ARC did not exist. While creating ARC, Apple decided that a warning should be generated for these methods as a way of guiding developers toward using other means to explicitly define how memory should be handled when sending arbitrary messages via a named selector. In Objective-C, developers are able to do this by using C style casts on raw function pointers.

With the introduction of Swift, Apple has documented the performSelector: family of methods as "inherently unsafe" and they are not available to Swift.
Over time, we have seen this progression:Early versions of Objective-C allow performSelector: (manual memory management)Objective-C with ARC warns for use of performSelector:Swift does not have access to performSelector: and documents these methods as "inherently unsafe"The idea of sending messages based on a named selector is not, however, an "inherently unsafe" feature. This idea has been used successfully for a long time in Objective-C as well as many other programming languages.
1 All Objective-C methods have two hidden arguments, self and _cmd that are implicitly added when you call a method.
2 Calling a NULL function is not safe in C. The guard used to check for the presence of the controller ensures that we have an object. We therefore know we'll get an IMP from methodForSelector: (though it may be _objc_msgForward, entry into the message forwarding system). Basically, with the guard in place, we know we have a function to call.
3 Actually, it's possible for it to get the wrong info if declare you objects as id and you're not importing all headers. You could end up with crashes in code that the compiler thinks is fine. This is very rare, but could happen. Usually you'll just get a warning that it doesn't know which of two method signatures to choose from
.4 See the ARC reference on retained return values and unretained return values for more details.

cited from http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown

  • In your code, replace occurrences of id as a return value with instancetype where appropriate. This is typically the case for init methods and class factory methods. Even though the compiler automatically converts methods that begin with “alloc,” “init,” or “new” and have a return type of id to return instancetype, it doesn’t convert other methods. Objective-C convention is to write instancetype explicitly for all methods.
    from https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html

  • UIButton of custom type can't set tint color. The porperties imageEdgeInsets and titleEdgeInsets can be used to set the position of image and title, respectively.

  • When hide navigation bar, the controller's view will adjust its frame, which leads to all its subviews adjust their frame respectively. To avoid that, the subviews can be added to the controller's view in viewwillappear after hide the navigation bar. ( ios 9, 6 plus)
    According to
    http://stackoverflow.com/questions/20380676/view-changes-its-own-frame-when-status-bar-gets-hidden-or-shown
    overlap a new window above navigation bar is also a solution, which however is not recommended because it is risky and dirty.

  • tableview status bar left a blank bar above the view, many one use magic number 20 to adjust the frame to solve this, however the solution is not suggested. Below links offer some hints for the proper solution, record that for the future use.
    http://stackoverflow.com/questions/18900428/ios-7-uitableview-shows-under-status-bar
    http://stackoverflow.com/questions/17074365/status-bar-and-navigation-bar-appear-over-my-views-bounds-in-ios-7

  • iOS capture packet
    1.Connect your iOS device to your Mac via USB.2.Get the UDID for the connected device from iTunes or organiser.3.Open terminal in your Mac4.type the following commands in the terminal$ ifconfig -l // First get the current list of interfaces.$ rvictl -s <udid> // Then run the tool with the UDID of the device. // This adds a new virtual network interface rvi0.$ ifconfig -l // Get the list of interfaces again, and you can see the newvirtual network interface, rvi0, added by the previous command.$ sudo tcpdump -i rvi0 -w ./output.pcap // Get the traced packets and save it to a fileNote : output.pacp is the packet traced file and will be located in the systems root directory When you're done you can stop the process with the following command.$ rvictl -x <udid>open the .pacp using wireshark and do your default procedures. Thats it !!!!!!!!

-- cited from https://ask.wireshark.org/questions/17559/packet-capturing-application-for-the-iphone

CGSize screenSize = [UIScreen mainScreen].bounds.size; float cameraAspectRatio = 4.0 / 3.0; float imageHeight = floorf(screenSize.width * cameraAspectRatio); float scale = ceilf((screenSize.height / imageHeight) * 10.0) / 10.0; _imagePicker.cameraViewTransform = CGAffineTransformMakeTranslation(0, (screenSize.height - imageHeight) / 2); _imagePicker.cameraViewTransform = CGAffineTransformScale(_imagePicker.cameraViewTransform,scale, scale);

  • Coordinate SystemsSince an image is a 2D map of pixels, the origin needs specification. Usually it’s the top-left corner of the image, with the y-axis pointing downwards, or at the bottom left, with the y-axis pointing upwards.There’s no “correct” coordinate system, and Apple uses both in different places.Currently, UIImage and UIView use the top-left corner as the origin and Core Image and Core Graphics use the bottom-left. This is important to remember so you know where to find the bug when Core Image returns an “upside down” image.

  • NSDateFormatter


    NSDateFormatter

  • Judge the iphone version

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)

iPhone 6 Plus 736x414 points 2208x1242 pixels 3x scale 1920x1080 physical pixels 401 physical ppi 5.5"iPhone 6 667x375 points 1334x750 pixels 2x scale 1334x750 physical pixels 326 physical ppi 4.7"iPhone 5 568x320 points 1136x640 pixels 2x scale 1136x640 physical pixels 326 physical ppi 4.0"iPhone 4 480x320 points 960x640 pixels 2x scale 960x640 physical pixels 326 physical ppi 3.5"iPhone 3GS 480x320 points 480x320 pixels 1x scale 480x320 physical pixels 163 physical ppi 3.5"

  • UITextField requires the view height larger than the font size 3 or more pixels that it can scroll when input reaches the end of the box. Otherwise the cursor just freeze over the end of the box, not the text, while in fact it on the end of the text if you print the property selectedRange.

  • create all-platform static library by lipo

        lipo -create INPUT_FILE ... -output OUTPUT_FILE
@interface MyClass : NSObject
@property (readonly, assign) NSInteger myInteger;
@end

Then redeclare in your class extension in the implementation file:

@interface MyClass ()
@property (readwrite, assign) NSInteger myInteger;
@end
@implementation MyClass
@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容