This profile

  • Topic: Apple will launch Tap to Pay
  • Tips: Solve the puzzling APP logout on iOS 15
  • Interview module: Dealloc use precautions and analysis
  • Excellent blog: ARM64 assembler introduction and application
  • Github: How to Cook
  • Development tools: file search application: EasyFind

This topic

@Zhangferry: Apple will launch Tap to Pay function on iPhone, which can complete the payment process at merchant terminal with a simple operation — Tap. The feature is secure via NFC and supports Apple Pay, contactless credit and debit cards as well as other digital wallets, meaning the iPhone will have a PO-like feature that allows customers to swipe their credit cards directly onto a merchant’s iPhone. This feature is only available on the iPhone XS and later models.

Stripe will be the first payment platform to offer Tap to Pay to its business customers on the iPhone. Other payment platforms and apps will be launched later this year.

Apple empowers businesses to accept contactless payments through Tap to Pay on iPhone

The development of Tips

Edited by FBY Zhan Fei

Resolve APP login on iOS 15 for no apparent reason

Recurring problems

After iOS 15 was officially released, we started receiving feedback from users who, when opening our App (Cookpad), were inexplicably forced to log out and return to the login page. Surprisingly, we didn’t see this problem when we tested the beta version of iOS 15.

We didn’t have a video or specific steps to recreate the problem, so I tried to launch the app in various ways in hopes of recreating it myself. I tried to reinstall the app, I tried to launch with and without an Internet connection, I tried to force out, and after 30 minutes of trying, I gave up and started replying that I couldn’t find the problem.

It wasn’t until I unlocked the phone again and started the Cookpad without doing anything, that I found the APP had just logged out of the login screen, as our users had reported!

I couldn’t exactly reproduce the problem after that, but it seemed to be related to taking a break from using the phone for a while and then using it again.

Narrow down the problem

I was concerned that reinstalling the application from Xcode might affect the recurrence of the problem, so I first examined the code and tried to narrow down the problem. Based on our implementation, I came up with three reasons to be skeptical.

  • 1.UserDefaultsThe data in the.
  • 2. An unexpected API call returns HTTP 401 and triggers logging out.
  • 3,KeychainAn error was thrown.

I was able to rule out the first two reasons for suspicion, thanks to some subtle behavior I observed after recreating the problem myself.

  • The login screen didn’t ask me to select a region — that suggestsUserDefaultsThere is no problem with the data in, because our “shown locale selection” preference is still in effect.
  • The main user interface is not shown, even briefly — indicating that no network request has been attempted, so it may be premature for the API to be the cause of the problem.

That leaves us with the Keychain, which leads me to the next question. What changed and why is it so hard to replicate?

Look for root causes

My debugging interface was useful, but it was missing something important to help answer all the questions: time.

I know the AppDelegate. Application (_ : before didFinishLaunchingWithOptions:), “protected data” is not available, but it still doesn’t make sense, because in order to reproduce this problem, I am doing the following:

3. Forcibly Exit the app. 4. Lock my device and leave it for 30 minutes

Every time I start the application again in Step 6, I’m 100% sure the device is unlocked, so I’m confident THAT I should be able to read from the Keychain in Appdelegate.init ().

It wasn’t until I looked at all these steps that things started to make a little bit of sense.

Take a closer look at the timestamp again:

  • main.swift– 11:38:47
  • AppDelegate.init()– 11:38:47
  • AppDelegate.application(_:didFinishLaunchingWithOptions:)– 12:03:04
  • ViewController.viewDidAppear(_:)– 12:03:04

The app itself launched 25 minutes before I actually unlocked the phone and clicked the app icon!

Now, I actually never thought there was such a big delay, it was actually @_Saagarjha who suggested I check the timestamp, and after that, he pointed me to this tweet.

Interesting iOS 15 optimizations. Duet is now trying to pre-empt third-party applications by running them through dyLD and pre-primary static initializers a few minutes before you click on an app icon. The application is then paused and the subsequent “boot” appears to be faster.

It all makes sense now. We didn’t test it initially because we probably didn’t give the iOS 15 beta enough time to “learn” our usage habits, so the problem only resurfaced in a real life scenario where the device thought I was going to launch the app soon. I still don’t know how this prediction comes about, but I’ll just chalk it up to “Siri intelligence “and leave it at that.

conclusion

Starting with iOS 15, the system may decide to “warm up” your app before the user actually tries to open it, which can increase the probability that protected data will be accessed when you think it should be unusable.

By waiting for the application (_ : didFinishLaunchingWithOptions:) entrust a callback to avoid App is affected by this, if you can, Refer to the UIApplication. IsProtectedDataAvailable (or entrusted by the corresponding callback/notification) and corresponding processing.

We still found a few non-lethal problem, in the application (_ : isProtectedDataAvailable didFinishLaunchingWithOptions:) in the attribute value is false, We don’t have any good options at this point except to postpone reading data from the keystring because it’s a system problem and not worth investigating further.

Reference: Fix APP inexplicable login on iOS 15 – Swift community

Parsing the interview

Hello World

Dealloc Usage precautions and resolution

Interview questions and applications for Dealloc have been covered in the weekly. For example, issue 38: dealloc in which thread to execute and issue 42: OOM governance FBAllocationTracker implementation principles, can be combined with today’s use of notes to learn together.

Avoid property access in dealloc

In many sources, it has been explicitly stated that access via attributes in dealloc should be avoided as much as possible, and member variables should be used instead.

In the initializer and dealloc methods, you should always read and write data directly from instance variables. 7 of Effective Objective-C 2.0

Always use accessor methods. Except in initializer methods and dealloc. – WWDC 2012 Session 413 – Migrating to Modern Objective-C

The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc. – Practical Memory Management

In addition to improving access efficiency, it can also prevent crashes. Some articles have introduced the reason for crash: During the process of destruction, the class structure is no longer complete. When accessor is used, messages are actually sent to the current instance, and crash may occur.

According to the debug analysis, the destructor process actually calls the dealloc overwritten by the instance first. Dealloc, cxx_destruct, Associated, Weak Reference, Side Table and other structures of superclass are processed in sequence. Finally, free is executed, so crash caused by structure destruction should not occur. Hope to have the classmate who understands to give advice

My personal understanding is that Apple does this because it does not want subclasses to affect the construction and destruction of their parent classes. For example, in the following code, a subclass affects its parent class’s dealloc process by overwriting the Associated method.

@interface HWObject : NSObject
@property(nonatomic) NSString* info;
@end
    
@implementation HWObject
- (void)dealloc {
    self.info = nil;
}
- (void)setInfo:(NSString *)info {
    if (info)
    {
        _info = info;
        NSLog(@ "% @"[NSStringstringWithString:info]); }}@end

@interface HWSubObject : HWObject
@property (nonatomic) NSString* debugInfo;
@end

@implementation HWSubObject
- (void)setInfo:(NSString *)info {
    NSLog(@ "% @"[NSString stringWithString:self.debugInfo]);
}
- (void)dealloc {
    _debugInfo = nil;
}
- (instancetype)init {
    if (self = [super init]) {
        _debugInfo = @"This is SubClass";
    }
    return self;
}
@end
Copy the code

HWSubObject:dealloc() releases the debugInfo variable, and then calls HWObject: Dealloc (), which uses the Associated setting info, and since subclasses override setInfo, So subclass setInfo. This function uses the released variable debugInfo. As mentioned above, subclasses end up influencing the parent’s destructor process by overriding Associated.

When does dealloc release variables

When the system calls dealloc, it automatically calls the destructor (.cxx_destruct) to release the variables. [NSObject dealloc] => _objc_rootDealloc => rootDealloc => object_dispose => objc_destructInstance => object_cxxDestruct => object_cxxDestructFromClass

static void object_cxxDestructFromClass(id obj, Class cls)
{
    // Iterate through self & superclass
        // SEL_cxx_destruct is assigned in Sel_init at map_images, which is the.cxx_destruct function
        dtor = (void(*)(id))
            lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
            / / execution(*dtor)(obj); }}}Copy the code

Along the superClass chain to query by lookupMethodInClassAndLoadCache SEL_cxx_destruct function, lookup to call. SEL_cxx_destruct is assigned by objC in Sel_init when map_images are initially called with the value.cxx_destruct.

Cxx_destruct is used to free variables and is automatically inserted when new variables are added to a class. You can use LLDB Watchpoint to listen for instance property changes and then check the stack information for validation.

Avoid using __weak in dealloc

- (void)dealloc {
    __weak typeof(self) weakSelf = self;
}
Copy the code

If __weak is used in dealloc, the dealloc will crash. Cannot form weak reference to instance (0x2813c4d90) of class xxx. It is possible that this object was over-released, or is in the process of deallocation. The reason for this error is that the Runtime determines whether the current object is being destructed while storing the weak reference count and throws an exception if it is being destructed

The core source code is as follows:

id  weak_register_no_lock(weak_table_t *weak_table, id referent_id,   id *referrer_id, WeakRegisterDeallocatingOptions deallocatingOptions) {
    / /... omit
        if (deallocating) {
            if (deallocatingOptions == CrashIfDeallocating) {
                _objc_fatal("Cannot form weak reference to instance (%p) of " "class %s. It is possible that this object was " "over-released, or is in the process of deallocation.", (void*)referent, object_getClassName((id)referent));
            } 
    / /... omit
}

Copy the code

Avoid using GCD in dealloc

For example, a class that is often used in child threads needs to use an NSTimer timer internally. Since the timer needs to be added to NSRunloop, it is added to the main thread for simplicity, and the timer has one special feature: The release and creation of the timer must be in the same thread, so the release also needs to be in the main thread, example code is as follows (the above code is only an example code, not the actual development use) :

- (void)dealloc {
		[self invalidateTimer];
}

- (void)fireTimer {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        if(! weakSelf.timer) { weakSelf.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
                NSLog(@"TestDeallocModel timer:%p", timer);
            }];
            [[NSRunLoop currentRunLoop] addTimer:weakSelf.timer forMode:NSRunLoopCommonModes]; }}); } - (void)invalidateTimer {
    dispatch_async(dispatch_get_main_queue(), ^{
        / / crash position
        if (self.timer) {
            NSLog(@"TestDeallocModel invalidateTimer:%p model:%p".self->_timer, self);
            [self.timer invalidate];
            self.timer = nil; }}); } - (vodi)main {dispatch_async(dispatch_get_global_queue(0.0), ^{
        HWSubObject *obj = [[HWSubObject alloc] init];
        [obj fireTimer];
    });
}
Copy the code

InvalidateTimer ::if (self.timer) : EXC_BAD_ACCESS The reason is simple, because dealloc eventually calls free() to free memory, and then GCD attempts to access self with a wild pointer, so an error is reported.

You can use performSelector instead of the GCD implementation to ensure that thread operations complete before dealloc.

Summary: The interview for memory management and dealloc related investigation should not be very complex, it is recommended to peruse a source code, understand dealloc call timing and the whole release process, and then understand the matters needing attention, basically can solve dealloc related interview questions at one time.

  • Why can’t we use accessor methods in init and dealloc functions
  • What else should Dealloc pay attention to under ARC?
  • Practical Memory Management

Good blog

Edit: King Pilaf is here

The topic of this excellent blog is: Getting started with ARM64 assembly. Assembly code is both familiar and unfamiliar territory for most of us developers, and we are familiar with assembly as we encounter it on a daily basis. However, after we encounter assembly, most people may not know what assembly code does, and do not know what problems can be solved by assembly code and often choose to ignore it, so assembly code is strange. In this blog, I’ve collected three assembler tutorials to take you into the ARM64 assembler world.

What will I gain from reading and learning?

After a complete reading of the three sets of learning tutorials, we can read some simple logic assembly code, more importantly, there is a method for troubleshooting difficult bugs.

Need a foundation?

I don’t know much about compilations. During reading and the course of the semester, I found that the contents that need thinking and understanding were well introduced by the authors.

1, [C in ASM(ARM64)] — from Zhi hu: Zhi Bin

King Pirav: I recommend reading this series first. The author explains the relationship between source code and assembly syntactically. For example, what does assembly code look like for arrays? Structure-specific assembly code. After reading, we can have some understanding of the stack, and can read less complex assembly code, and can translate some manual source code into assembly code with instruction set instructions.

IOS assembly primer — From Nuggets: Soulghost

King Pilaf: Master Page produced classic tutorials. More on seeing and applying assembly from an iOS developer’s perspective than in the previous series, for example, how to analyze the implementation of NSClassFromString using assembly code. The overall depth of the articles has also increased, so if you have some compilation skills, you can start with this series.

3. In-depth series of articles on the bottom of iOS system — From Digging gold: Ouyang Big Brother 2013

King Piraf: a very comprehensive and in-depth collection of underlying related articles. With the groundwork laid in the previous two articles, you can read this series to expand on it. In addition, the author also led us step by step to use assembly code to troubleshoot the wild pointer problem in the in-depth crash solution of iOS system. As a beginner we can quickly feel the benefits.

Learning materials

Mimosa

Programmer’s Guide to Cooking

Address: github.com/Anduin2017/…

A community-driven and maintained cooking guide. Here you can learn how various dishes are made, as well as some kitchen common sense and knowledge. It is interesting that most recipes in the warehouse describe the details and dosage accurately in the production process. For example, inaccurate descriptions are not allowed in recipes, such as “right amount, small amount, medium amount and appropriate”. Very strict and accurate requirements, for almost every recipe is concise and accurate, very interesting, also welcome everyone to contribute it ~

Tools recommended

CoderStar

EasyFind

Address: easyfind.en.softonic.com/mac

Software status: Free

Software Introduction:

A small but powerful file search application comparable to Everything for Windows.

About us

IOS Fish weekly, mainly share the experience and lessons encountered in the development process, high-quality blog, high-quality learning materials, practical development tools, etc. The weekly warehouse is here: github.com/zhangferry/… If you have a good content recommendation, you can submit it through the way of issue. You can also apply to be our resident editor to maintain the weekly. Also can pay attention to the public number: iOS growth road, backstage click into the group communication, contact us, get more content.

Phase to recommend

IOS Fishing Weekly 43

IOS Fishing Week 42nd issue

IOS fishing weekly 41 issue

IOS Fishing Weekly 40th issue