App
当在AppDelegate生命周期内,如果出现新的窗口被请求的时候会自动调用AppDelegate的configurationForConnectingSceneSession方法对新的UIScene进行配置,同时就会创建新的SceneDelegate,在SceneDelegate被创建后就会调用SceneDelegate的willConnectToSession方法,这个方法可以选择性配置创建的UIWindow,然后将UIScene和UIWindow连接上,如果使用了storyboard则这个window的属性也会自动被初始化和连接到scene上。
当scene进入后台或者被丢弃时会调用sceneDidDisconnect,会释放任何和scene有关的资源,这些资源可以在下次scene重新连接的时候重新创建
关键API
UIApplicationMain(argc, argv, nil, appDelegateClassName);
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是整个应用程序的一个抽象,负责存储应用程序的状态
根据第四个参数创建了一个应用程序代理类对象
此代理类对象一定是系统创建的,而且只有一个
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的方法(并不作为subView)
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里面可以添加
viewDidLoad
是viewControl控制的view的生命起点,创建出这个view之后第一个调用的方法,且这个方法只会调用一次文章来源:https://www.toymoban.com/news/detail-493124.html
UITapGestureRecognizer(手势识别器(gesture recognizer))
可以识别用户对该视图进行的单次或多次轻触操作。当手势被识别时,可以触发相应的操作或调用指定的处理方法。文章来源地址https://www.toymoban.com/news/detail-493124.html
// 创建一个 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");
}
到了这里,关于UIKit-基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!