UIKit-基础

App

当在AppDelegate生命周期内,如果出现新的窗口被请求的时候会自动调用AppDelegate的configurationForConnectingSceneSession方法对新的UIScene进行配置,同时就会创建新的SceneDelegate,在SceneDelegate被创建后就会调用SceneDelegate的willConnectToSession方法,这个方法可以选择性配置创建的UIWindow,然后将UIScene和UIWindow连接上,如果使用了storyboard则这个window的属性也会自动被初始化和连接到scene上。

当scene进入后台或者被丢弃时会调用sceneDidDisconnect,会释放任何和scene有关的资源,这些资源可以在下次scene重新连接的时候重新创建

sendAction:to:from:forEvent:

一般是在UIControl对象被touch的时候调用,会dispatch一个action method
给目标对象 如果没有特殊指定对象就会发给first responder,所以Application是继承自UIControl 是会自动调用的
实际上这个就是底层实现,
比如说你添加了一个button,然后添加在view上,给这个button添加了一个action叫btnAction,则当你点击button的时候会先执行 sendAction:btnAction to:view sender:button event:UITouchEvent
然后 就调用btnAction

注意

如果你要动态替换掉sendAction方法你需要在重写方法里面再添加一次 主要是因为原方法和新方法做了替换,所以先调用原方法的时候因为替换 调用的是新方法,然后在新方法里面调用了新方法(由于替换 调用的是原方法)

创建UIApplication + extern.m

#import "UIApplication + extern.h"
#import <objc/runtime.h>
#import <objc/message.h>

@implementation UIApplication(AppExtern)

//自动调用 在加载app的时候会调用
+ (void)load {
    
    
    NSLog(@"%s",__func__);
    [self test_swizzleMethod:@selector(sendAction:to:from:forEvent:) withMethod:@selector(test_sendAction:to:from:forEvent:) error:nil];
}

//将使用test_sendAction动态替换sendAction 注意 这个方法里面重复调用了test_sendAction,原因是将test_sendAction和sendAction做了交换,首先是系统自动调用sendAction(由于做了交换 所以第一次实际上调用的是test_sendAction),然后在test_sendAction里面调用test_sendAction(由于做了交换,此时实际上调用的是sendAction)
- (void)test_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event
{
    
    
    NSLog(@"%s",__func__);
    [self test_sendAction:action to:target from:sender forEvent:event];
}

//动态替换方法
+ (BOOL)test_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ {
    
    
    Method origMethod = class_getInstanceMethod(self, origSel_);
    if (!origMethod) {
    
    
        NSLog(@"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self class]);
        return NO;
    }

    Method altMethod = class_getInstanceMethod(self, altSel_);
    if (!altMethod) {
    
    
        NSLog(@"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self class]);
        return NO;
    }

    class_addMethod(self,
                    origSel_,
                    class_getMethodImplementation(self, origSel_),
                    method_getTypeEncoding(origMethod));
    class_addMethod(self,
                    altSel_,
                    class_getMethodImplementation(self, altSel_),
                    method_getTypeEncoding(altMethod));

    method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_));
    return YES;
}
@end

storyboard

想要指定storyboard显示的view 目前还没确定

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *rootViewController = [storyboard instantiateInitialViewController];

instantiateInitialViewController这个方法会自动创建并返回 storyboard 文件中的第一个视图控制器,要求 storyboard 文件中必须有一个标记为 “Is Initial View Controller” 的视图控制器。这个属性可以在 storyboard 中的视图控制器属性检查器中进行设置。如果 storyboard 中没有设置初始视图控制器,或者设置了多个初始视图控制器,那么 instantiateInitialViewController 方法将返回 nil

UIWindowSceneDelegate

这个协议里面约定了一定有一个window属性,所以在创建新项目时系统自动创建的SceneDelegate里面会自带@property (strong, nonatomic) UIWindow * window;这个也没办法改名,比如改成mainWindow都是不行的,所以应该是改不了这个window,默认就是用这个

UINavigation

相当于一个viewController的stack,用于管理view的显示。在window连接了一个NavigationController后会显示堆顶的viewController的view。所以如果要显示一个view就push进去,不要了就pop出来

显示View的方法

presentViewController,这种方法如果显示动画 view是从下往上显示出来的
pushViewController 是从右往左显示出来

创建时必须要有一个viewController作为rootViewController。

视图位移

其他还有缩放和旋转

self.btn.transform = CGAffineTransformTranslate(self.btn.transform,20, 20);//以btn当前位置做偏移 可以连续偏移的
self.btn.transform = CGAffineTransformEqualToTransform(20, 20);//偏移到指定位置
self.btn.transform = CGAffineTransformIdentity;//清空之前的操作

scene

Application Session Role

一是般填在plist里面
在这里插入图片描述

UIWindowSceneSessionRoleApplication://表示应用程序场景是主要的应用程序场景,用于承载应用程序的主要用户界面。
UIWindowSceneSessionRoleExternalDisplay://表示应用程序场景用于外部显示,如外接显示器或投影仪等。
UIWindowSceneSessionRoleAssistant://表示应用程序场景用于显示助理界面,例如 Siri 提示、CarPlay 等。
UIWindowSceneSessionRolePresentation://表示应用程序场景用于呈现其他内容,例如弹出式菜单、通知中心等。

如果在这个plist里面添加了Storyboard Name -> Main
表示启用Main.storyBoard,则window的属性会被自动除时候,并且连接到当前的scene上 也就是相关的SceneDelegate的scene上
如果不想用storyboard那就必须手动代码创建一个window

//sceneDelegate.m
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    
    
    NSLog(@"%s",__FUNCTION__);
    self.customVC = [[customVCViewController alloc]init];
    UINavigationController *nv = [[UINavigationController alloc]initWithRootViewController:self.customVC];
    float width = [UIScreen mainScreen].bounds.size.width;
    float height = [UIScreen mainScreen].bounds.size.height;
    self.window = [[UIWindow alloc]initWithWindowScene:(UIWindowScene *)scene];
    
    self.window.rootViewController = nv;
    // 设置窗口可见
    [self.window makeKeyAndVisible];
    
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
}

UIViewController

如果UIViewController不关联xib文件,UIViewController在init的时候会自动创建一个view
如果你想让VC去管理自定义的view可以在- (void)loadView 里面添加自定义的view 但是这个view必须自己实现相关的设置比如说在view init的时候要设置相应的约束或者rect等等。

viewController的 view 属性被首次访问时,系统会调用 loadView 方法来加载view并将其赋值给 view 属性。
一般是系统自动调用 然后创建UIView作为viewController.view的值,但是当你想加载自定义view的时候就需要在这里将view更改为自定义view

- (void)loadView
{
    
    
    customView* customV = [[customView alloc]init];
    self.view = customV;
}

原先添加viewController.view上面的subView是在viewController的viewDidLoad里面添加,但是如果自定义了view,那就是在view的init里面可以添加

UITapGestureRecognizer(手势识别器(gesture recognizer))

可以识别用户对该视图进行的单次或多次轻触操作。当手势被识别时,可以触发相应的操作或调用指定的处理方法。

// 创建一个 UITapGestureRecognizer 对象
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];

// 设置手势的属性(可选)
tapGesture.numberOfTapsRequired = 1; // 单击次数要求
tapGesture.numberOfTouchesRequired = 1; // 手指数量要求

// 将手势添加到视图上
[self.view addGestureRecognizer:tapGesture];

// 处理手势的方法
- (void)handleTap:(UITapGestureRecognizer *)gesture {
    
    
    // 在此处执行相应的操作
    NSLog(@"Tap gesture recognized");
}

猜你喜欢

转载自blog.csdn.net/qq_43535469/article/details/131293218