白季飞龙的个人主页

iOS大杂烩

iOS是苹果公司开发的专用移动端操作系统,用于iPhone和iPad。iOS开发用到的主流编程语言是Objective-C。

Hello Objective-C

Hello World

示例代码

# import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"Hello, World!");
    }
    return 0;
}

控制台输出

2018-12-22 22:28:44.249 hellooc[1710:8656] Hello, World!

要点

面向对象的Objective-C

示例代码

//
//  main.m
//  hellooc
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface MyColor : NSObject {
    int red;
    int green;
    int blue;
}

/**
 * #Java: new MyColor(x, y, z)
 *
 * @param aRed
 * @param aGreen
 * @param aBlue
 * @return
 */
- (instancetype)initWithRed:(int)aRed green:(int)aGreen blue:(int)aBlue;

/**
 * #Java: MyColor.newInstance(x, y, z)
 * @param aRed
 * @param aGreen
 * @param aBlue
 * @return
 */
+ (instancetype)colorWithRed:(int)aRed green:(int)aGreen blue:(int)aBlue;


@end

@implementation MyColor

/**
 * # Java: new MyColor()
 * @return
 */
- (instancetype)init {
    self = [super init];
    if (self) {
        red = 1;
        green = 2;
        blue = 3;
    }
    return self;
}

- (instancetype)initWithRed:(int)aRed green:(int)aGreen blue:(int)aBlue {
    self = [super init];
    if (self) {
        red = aRed;
        green = aGreen;
        blue = aBlue;
    }

    return self;
}

+ (instancetype)colorWithRed:(int)aRed green:(int)aGreen blue:(int)aBlue {
    return [[self alloc] initWithRed:aRed green:aGreen blue:aBlue];
}


/**
 * #Java: toString()
 * @return
 */
- (NSString *)description {
    NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])];
    [description appendFormat:@"red=%i", red];
    [description appendFormat:@", green=%i", green];
    [description appendFormat:@", blue=%i", blue];
    [description appendString:@">"];
    return description;
}

@end

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        MyColor *myColor;

        NSLog(@"Before initialization:");
        NSLog(@"myColor = %@", myColor);

        myColor = [MyColor new];
        NSLog(@"After initialization of custom constructor:");
        NSLog(@"myColor = %@", myColor);

        myColor = [[MyColor alloc] initWithRed:0 green:255 blue:0];
        NSLog(@"Initialized with custom multiple-parameters constructor:");
        NSLog(@"myColor = %@", myColor);

        myColor = [MyColor colorWithRed:111 green:111 blue:111];
        NSLog(@"Initialized with static method:");
        NSLog(@"myColor = %@", myColor);
    }
    return 0;
}

示例输出

2018-12-22 22:29:17.847 hellooc[1732:8941] Before initialization:
2018-12-22 22:29:17.847 hellooc[1732:8941] myColor = (null)
2018-12-22 22:29:17.847 hellooc[1732:8941] After initialization of custom constructor:
2018-12-22 22:29:17.847 hellooc[1732:8941] myColor = <MyColor: red=1, green=2, blue=3>
2018-12-22 22:29:17.847 hellooc[1732:8941] Initialized with custom multiple-parameters constructor:
2018-12-22 22:29:17.848 hellooc[1732:8941] myColor = <MyColor: red=0, green=255, blue=0>
2018-12-22 22:29:17.848 hellooc[1732:8941] Initialized with static method:
2018-12-22 22:29:17.848 hellooc[1732:8941] myColor = <MyColor: red=111, green=111, blue=111>

要点

Hello Cocoa

iOS应用的生命周期

测试代码 AppDelegate.m

//
//  AppDelegate.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import "AppDelegate.h"


@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSLog(@"[app] didFinishLaunchingWithOptions");
    return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    NSLog(@"[app] applicationWillResignActive");

}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    NSLog(@"[app] applicationDidEnterBackground");

}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    NSLog(@"[app] applicationWillEnterForeground");
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    NSLog(@"[app] applicationDidBecomeActive");
}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    NSLog(@"[app] applicationWillTerminate");
}


@end

控制台输出

用户操作流程: 打开应用 => 按Home回桌面 => 再次打开应用 => 双击Home弹出进程列表 => 划掉应用

2018-12-22 23:32:30.685585+0800 hellococoa[2497:25432] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2018-12-22 23:32:30.730883+0800 hellococoa[2497:25432] [app] didFinishLaunchingWithOptions
2018-12-22 23:32:30.737519+0800 hellococoa[2497:25432] [app] applicationDidBecomeActive

2018-12-22 23:32:45.269746+0800 hellococoa[2497:25432] [app] applicationWillResignActive
2018-12-22 23:32:45.844597+0800 hellococoa[2497:25432] [app] applicationDidEnterBackground

2018-12-22 23:32:54.979323+0800 hellococoa[2497:25432] [app] applicationWillEnterForeground
2018-12-22 23:32:55.265910+0800 hellococoa[2497:25432] [app] applicationDidBecomeActive

2018-12-22 23:33:04.389439+0800 hellococoa[2497:25432] [app] applicationWillResignActive

2018-12-22 23:33:19.848464+0800 hellococoa[2497:25432] [app] applicationDidEnterBackground
2018-12-22 23:33:19.851948+0800 hellococoa[2497:25432] [app] applicationWillTerminate

LaunchScreen与Main两个StoryBoard

iOS项目默认有两个StoryBoard,一个叫LaunchScreen.storyboard,一个叫Main.storyboard。显然,LaunchScreen是开屏界面,Main是主界面。

启动App后,先显示LaunchScreen,然后渐变过度到Main。过度动画大约持续1秒

注意,XCode10的控件库的位置变了,XCode右上角有个专用的Library按钮。快捷键Cmd+Shift+L

移除StoryBoard

步骤:

  1. 直接删除两个StoryBoard文件
  2. 在项目属性(点击导航栏的项目名,进入项目属性页)的General => Deployment Info 下将Main interface置空(本质上是修改项目的plist文件)
  3. 修改AppDelegate.m,手动关联AppDelegate与ViewController

示例代码片段:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [UIWindow new];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor redColor];

    ViewController *viewController = [[ViewController alloc] init];
    viewController.view.backgroundColor = UIColor.redColor;

    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

注意

单文件iOS应用

示例代码

//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    // 1. Create window
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor magentaColor];
    // 2. Bind window to ViewController
    self.window.rootViewController = [[MyViewController alloc] init];
    // 3. Show window
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

iOS布局

演示: 将屏幕水平均分为两块,这两块的间距和他们相对于屏幕边缘的边距都为10

1. 使用官方的约束布局

示例代码
//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
- (void)loadView {
    [super loadView];
    self.view = [[UIView alloc] init];

    UIView *leftView = [[UIView alloc] init];
    UIView *rightView = [[UIView alloc] init];

    leftView.backgroundColor = [UIColor magentaColor];
    rightView.backgroundColor = [UIColor purpleColor];

    leftView.translatesAutoresizingMaskIntoConstraints = NO;
    rightView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:leftView];
    [self.view addSubview:rightView];

    [self.view addConstraints:@[
            // 固定左布局的上、左、下边界
            [NSLayoutConstraint constraintWithItem:leftView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:10],
            [NSLayoutConstraint constraintWithItem:leftView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10],
            [NSLayoutConstraint constraintWithItem:leftView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10],
            // 固定右布局的上、右、下边界
            [NSLayoutConstraint constraintWithItem:rightView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:10],
            [NSLayoutConstraint constraintWithItem:rightView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-10],
            [NSLayoutConstraint constraintWithItem:rightView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10],
            // 确定左、右布局的相对位置
            [NSLayoutConstraint constraintWithItem:rightView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:leftView attribute:NSLayoutAttributeRight multiplier:1.0 constant:10],
            // 确定左、右布局的相对大小
            [NSLayoutConstraint constraintWithItem:rightView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:leftView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]
    ]];
}

@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    // 1. Create window
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    // 2. Bind window to ViewController
    self.window.rootViewController = [[MyViewController alloc] init];
    // 3. Show window
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}
注意:

2. 使用官方的VFL布局

VFL: Visual Format Lanuguage

示例代码
//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
- (void)loadView {
    [super loadView];
    self.view = [[UIView alloc] init];

    UIView *leftView = [[UIView alloc] init];
    UIView *rightView = [[UIView alloc] init];

    leftView.backgroundColor = [UIColor magentaColor];
    rightView.backgroundColor = [UIColor purpleColor];

    leftView.translatesAutoresizingMaskIntoConstraints = NO;
    rightView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:leftView];
    [self.view addSubview:rightView];

    NSDictionary *metrics = @{@"space": @10};
    NSDictionary *views = NSDictionaryOfVariableBindings(leftView, rightView);
    [self.view addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"H:|-space-[leftView]-[rightView(==leftView)]-space-|"
                                options:nil
                                metrics:metrics
                                  views:views]];
    [self.view addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"V:|-space-[leftView]-space-|"
                                options:nil
                                metrics:metrics
                                  views:views]];
    [self.view addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"V:|-space-[rightView]-space-|"
                                options:nil
                                metrics:metrics
                                  views:views]];
}

@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    // 1. Create window
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    // 2. Bind window to ViewController
    self.window.rootViewController = [[MyViewController alloc] init];
    // 3. Show window
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}
注意:

3. 使用AutoLayout的封装库Masonry进行布局

Mansonry是对AutoLayout的封装,可以通过CocoaPods安装

示例代码
//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <Masonry/View+MASAdditions.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
- (void)loadView {
    [super loadView];
    self.view = [[UIView alloc] init];

    UIView *leftView = [[UIView alloc] init];
    UIView *rightView = [[UIView alloc] init];

    leftView.backgroundColor = [UIColor magentaColor];
    rightView.backgroundColor = [UIColor purpleColor];

    leftView.translatesAutoresizingMaskIntoConstraints = NO;
    rightView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:leftView];
    [self.view addSubview:rightView];

    // 左布局相对于父布局
    [leftView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).with.offset(10);
        make.left.equalTo(self.view.mas_left).with.offset(10);
        make.bottom.equalTo(self.view.mas_bottom).with.offset(-10);
    }];

    // 右布局相对于父布局
    [rightView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).with.offset(10);
        make.right.equalTo(self.view.mas_right).with.offset(-10);
        make.bottom.equalTo(self.view.mas_bottom).with.offset(-10);
    }];

    // 右布局相对于左布局
    [rightView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(leftView.mas_right).with.offset(10);
        make.width.equalTo(leftView.mas_width);
    }];
}

@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    self.window.rootViewController = [[MyViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

4. Flex布局

iOS可以通过第三方库YogaKit实现Flex布局

示例代码
//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <YogaKit/UIView+Yoga.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
- (void)viewDidLoad {
    UIView *root = self.view;
    root.backgroundColor = [UIColor redColor];

    root.yoga.isEnabled = YES;
    root.yoga.flexDirection = YGFlexDirectionRow;
    root.yoga.justifyContent = YGJustifyCenter;
    root.yoga.alignItems = YGAlignStretch;
    root.yoga.padding = YGPointValue(10);

    UIView *leftView = [UIView new];
    leftView.yoga.isEnabled = YES;
    leftView.yoga.flexGrow = 1.0;
    leftView.backgroundColor = [UIColor blueColor];

    UIView *rightView = [UIView new];
    rightView.yoga.isEnabled = YES;
    rightView.yoga.flexGrow = 1.0;
    rightView.yoga.marginLeft = YGPointValue(10);
    rightView.backgroundColor = [UIColor greenColor];

    [root addSubview:leftView];
    [root addSubview:rightView];
    [root.yoga applyLayoutPreservingOrigin:NO];
}
@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    self.window.rootViewController = [[MyViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}
注意

CocoaPods的安装与使用

CocoaPods是Objective-C的依赖管理工具

安装CocoaPods

CocoaPods是用Ruby写的,需要通过gem安装

gem install cocoapods

注意:

使用CocoaPods

  1. pod init 初始化CocoaPods项目
  2. vim Podfile 编辑项目依赖
  3. pod install 安装项目依赖
  4. open App.xcworkspace 使用CocoaPods创建的工作空间重新打开项目

示例Podfile

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'hellococoa' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for hellococoa
  pod 'AFNetworking', '~> 2.6'
  pod 'Masonry'

  target 'hellococoaTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'hellococoaUITests' do
    inherit! :search_paths
    # Pods for testing
  end
end

Toast

iOS没有内置类似Android的Toast,需要自己定义或使用第三方库Toast

安装方式: pod 'Toast', '~> 4.0.0'

示例代码

//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <YogaKit/UIView+Yoga.h>
#import <Toast/UIView+Toast.h>

@interface MyViewController : UIViewController
@end

@implementation MyViewController
- (void)viewDidLoad {
    UIView *root = self.view;
    root.backgroundColor = [UIColor cyanColor];

    root.yoga.isEnabled = YES;
    root.yoga.flexDirection = YGFlexDirectionRow;
    root.yoga.justifyContent = YGJustifyCenter;
    root.yoga.alignItems = YGAlignCenter;
    root.yoga.padding = YGPointValue(10);

    UIButton *button = [UIButton new];
    button.backgroundColor = [UIColor blueColor];
    [button setTitle:@"Click Me" forState:UIControlStateNormal];
    button.yoga.isEnabled = YES;
    button.yoga.flexGrow = 1;
    [button addTarget:self action:@selector(onClicked) forControlEvents:UIControlEventTouchUpInside];

    [root addSubview:button];
    [root.yoga applyLayoutPreservingOrigin:NO];
}

- (void)onClicked {
    [self.view makeToast:@"Hello World" duration:1 position:CSToastPositionBottom];
}

@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    self.window.rootViewController = [[MyViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

UITableView

示例代码

//
//  main.m
//  hellococoa
//
//  Created by bj on 2018-12-22.
//  Copyright © 2018 bj. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <YogaKit/UIView+Yoga.h>
#import <Toast/UIView+Toast.h>

@interface MyViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@end

@implementation MyViewController
- (void)viewDidLoad {
    UIView *root = self.view;
    root.backgroundColor = [UIColor cyanColor];

    root.yoga.isEnabled = YES;
    root.yoga.flexDirection = YGFlexDirectionColumn;
    root.yoga.justifyContent = YGJustifyCenter;
    root.yoga.alignItems = YGAlignStretch;
    root.yoga.padding = YGPointValue(50);

    UILabel *label = [UILabel new];
    label.text = @"UITableView Demo";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    label.backgroundColor = [UIColor blueColor];
    label.yoga.isEnabled = YES;
    label.yoga.flexGrow = 1;
    label.yoga.padding = YGPointValue(10);

    UITableView *tableView = [UITableView new];
    tableView.yoga.isEnabled = YES;
    tableView.yoga.flexGrow = 1;
    tableView.delegate = self;
    tableView.dataSource = self;

    [root addSubview:label];
    [root addSubview:tableView];
    [root.yoga applyLayoutPreservingOrigin:NO];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 100;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"my-id"];
    if (cell == nil) {
        NSLog(@"Creating item: %ld", indexPath.item + 1);
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"my-id"];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Item %ld", indexPath.item + 1];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view makeToast:[NSString stringWithFormat:@"You tapped item %ld", indexPath.item + 1] duration:0.1 position:CSToastPositionBottom];
}

@end

@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic) UIWindow *window;
@end

@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] init];
    self.window.frame = UIScreen.mainScreen.bounds;
    self.window.backgroundColor = [UIColor grayColor];
    self.window.rootViewController = [[MyViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"%@", NSStringFromClass([MyAppDelegate class]));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

示例控制台输出

2018-12-23 17:29:19.772025+0800 hellococoa[22269:296737] MyAppDelegate
2018-12-23 17:29:19.794322+0800 hellococoa[22269:296737] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2018-12-23 17:29:19.860195+0800 hellococoa[22269:296737] Creating item: 1
2018-12-23 17:29:19.862716+0800 hellococoa[22269:296737] Creating item: 2
2018-12-23 17:29:19.863633+0800 hellococoa[22269:296737] Creating item: 3
2018-12-23 17:29:19.864310+0800 hellococoa[22269:296737] Creating item: 4
2018-12-23 17:29:19.864963+0800 hellococoa[22269:296737] Creating item: 5
2018-12-23 17:29:19.865550+0800 hellococoa[22269:296737] Creating item: 6
2018-12-23 17:29:19.866112+0800 hellococoa[22269:296737] Creating item: 7
2018-12-23 17:29:19.866662+0800 hellococoa[22269:296737] Creating item: 8
2018-12-23 17:29:19.867207+0800 hellococoa[22269:296737] Creating item: 9
2018-12-23 17:29:19.867728+0800 hellococoa[22269:296737] Creating item: 10
2018-12-23 17:29:19.868293+0800 hellococoa[22269:296737] Creating item: 11
2018-12-23 17:29:25.746864+0800 hellococoa[22269:296737] Creating item: 12
2018-12-23 17:29:33.371258+0800 hellococoa[22269:296737] Creating item: 79

截图

UITableView

注意

文章首发: https://baijifeilong.github.io


漫漫路,莫论逍遥;潜心修,只为悟道