21. iOS应用框架(上)

主要讲解了 Project 文件目录整理分类,Storyboard 和代码结合使用,Constraints 的使用。稍后在项目里面实践一下。

有提到 [UIScreen mainScreen].bounds 的问题。

我之前就研究过,见:http://gewill.org/2015/08/04/UIScreen-mainScreen-bounds-in-Xcode-7-Beta-4/

23. iOS应用框架(下)

主要演示 Storyboard 的自动布局和代码管理跳转和动画过度。但是总感觉有点基本上是在 AppDelegate 中管理 Storyboard 的跳转关系,实不如 Storyboard references 清晰明了,且不妨碍分工开发。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//  AppDelegate.h
// BLDemo05


#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


/**
* 声明一个 UINavigationController 属性,作为 rootViewController
*/
@property (strong, nonatomic) UINavigationController *loginNavigationVC;


/**
* 使用代码加载 Login.storyboard 的函数
*/
- (void)loadLoginView;
/**
* 使用代码加载 Login.storyboard 的函数
*/
- (void)loadMainView;

@end


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//  AppDelegate.m
// BLDemo05


#import "AppDelegate.h"
#import "BLUserInfoViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (void)loadLoginView {
// 读取 Login.storyboard, 压入 rootViewController(loginNavigationVC)
UIStoryboard *loginStoryboard
= [UIStoryboard storyboardWithName:@"Login"
bundle:[NSBundle mainBundle]];
self.loginNavigationVC = loginStoryboard.instantiateInitialViewController;
self.window.rootViewController = self.loginNavigationVC;
}


- (void)loadMainView {

// 1 - 读取 UserInfo.storyboard, 压入 BLUserInfoViewController(userInfoVC), 一并压入 UINavigationController(navc)
UIStoryboard *userInfoStoryboard
= [UIStoryboard storyboardWithName:@"UserInfo" bundle:[NSBundle mainBundle]];

BLUserInfoViewController *userInfoVC
= [userInfoStoryboard instantiateViewControllerWithIdentifier:@"BLUserInfoViewController"];

UINavigationController *navc
= [[UINavigationController alloc] initWithRootViewController:userInfoVC];

// 2 - 添加 UINavigationController 标题
navc.tabBarItem.title = @"userInfo";

// 3 - 新建一个 UITabBarController(tabBarC),并设为 rootViewController
UITabBarController *tabBarC = [[UITabBarController alloc] init];
tabBarC.viewControllers = @[navc];

self.window.rootViewController = tabBarC;

// 4 - 添加过度效果
[self.window addSubview:self.loginNavigationVC.view];

[UIView animateWithDuration:0.3
animations:^{
self.loginNavigationVC.view.alpha = 0;
self.loginNavigationVC.view.frame = CGRectZero;
self.loginNavigationVC.view.transform = CGAffineTransformMakeScale(0.1, 0.1);
} completion:^(BOOL finished) {
self.loginNavigationVC = nil;
}];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

// App 启动,调用 loadLoginView 函数
[self loadLoginView];

return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
}

- (void)applicationWillTerminate:(UIApplication *)application {
}

@end

App Distributio

  1. iTunes Connet > MyApps > add App
  2. Xcode
  • Product > Acrchive
  • Window > Organizer > Submit to App Store
  1. iTunes Connet > MyApps > Prerelease
  • Builds: Turn on TestFlight Beta Testing
  • Add Internal or External Testers
  1. Click Open in TestFlight in email from iTunes Store on your iPhone

More in App Distribution Guide

Dash 3 Snippets 全局使用很好很强大,稍后添加一些 Swift 和常用邮箱和用户名。

下面是打开 MacDown 软件直接开始文章,不用去 Terminal 新建文章。
定义为:hexon

1
2
3
4
5
6
7
8
9

title: __placeholder__

date: @date @time

---

@cursor

##《Objective-C 高级编程》测试题

  1. 设计一个动物基类。
    要求: A、抽象出动物的基本属性(包括:性别、名字、体重)。 B、抽象出动物的基本能力(包括:发声)。 C、基本属性性别用枚举定义。
  2. 由题目 1 设计好的动物基类继承,设计一个新的鸟和鱼的子类。 要求:
    A、鸟类需要扩展颜色属性。 B、鸟类需要扩展飞的方法(方法体输出打印出飞行状态即可)。 C、鱼类需要扩展颜色属性。 D、鱼类需要扩展出游的方法(方法体输出打印游的状态即可)。
  3. 设计好 1、2 两个题目要求的类后,创建一个数组。使用一个循环,生成 10 只鸟、10 条鱼的对象,并将 10 只鸟、10 条鱼的对象加入到创建好的数组中。 最后,遍历这个数组对象,遍历到鸟对象时调用鸟儿飞的方法,遍历到鱼对象 时调用鱼儿游的方法。
  4. 考虑游戏中捞鱼, 随机器捞到 n 条鱼,纪录数量(被捞到的鱼认为对象的生 命周期结束,需要从内存中释放)。打鸟同理。

我的实现

github 源码:BLTest1

复习了类的定义,属性,实例方法,枚举,NSArray,随机数。
@孔祥波 老师点评了我的错误实现。自己回来改了很多,终于完成了,也加深了涉及知识点的应用。再次感觉 Google 真是个好东西。

###实现代码位置:

  1. 一二题目定义类为:GWAnimal,GWBird,GWFish
  2. 三四题对应代码在:ViewController.m 的 - (void)viewDidLoad {}中
    分别添加 // MARK No.3 和 // MARK: No.4,方便定位。

注释文档

其他的 Headerdoc 为练习写注释文档,尤其是// FIXME: Print a more readable result. 和 // TODO: Set a NSArray to init randomGWFish. 纯粹凑字数。测试 Swift 哪些可以用在 Objective-C 上。参看: Swift Documentation

其实这个实现是 Objective-C,应该看这一篇的 Documentation

  • @param [param] [Description]: Describes what value should be passed for this parameter
  • @return [Description]: Describes the return value of the method
  • @see [selector]: Provide “see also” reference to related method
  • @warning [description]: Call out exceptional or potentially dangerous behavior

To help speed up the process of documenting your project, you may want to check out the VVDocumenter-Xcode project, which automatically adds @param and @return labels for methods according to their signature.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

// MARK: No.3
NSMutableArray *animal = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
NSArray *birdNames = @[@"Parrot", @"Pelican", @"Raptor", @"Ural", @"Owls", @"BABY BLUE", @"AIDEN", @"BB", @"DAVE", @"CHILI"];
GWBird *randomGWBird = [[GWBird alloc] initWithName:birdNames[i] gender:(Gender)(arc4random() % 2) weight:(NSUInteger)(arc4random() % 100)];
randomGWBird.color = [UIColor whiteColor];
[animal addObject:randomGWBird];

// TODO: Set a NSArray to init randomGWFish.
GWFish *randomGWFish = [[GWFish alloc] initWithName:@"Fish" gender:(Gender)(arc4random() % 2) weight:(NSUInteger)(arc4random() % 100)];
randomGWFish.color = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0];
[animal addObject:randomGWFish];

}

for (int i = 0; i < [animal count]; i++) {
if ([animal[i] isKindOfClass:[GWBird class]]) {
[animal[i] fly];
} else if ([animal[i] isKindOfClass:[GWFish class]]) {
[animal[i] swim];
}
}



// MARK: No.4
int fishCount = 0;
int birdCount = 0;
NSUInteger randomRemoveNumber = (NSUInteger)(arc4random() % 20);
for (NSUInteger i = randomRemoveNumber; i > 0; i--) {

NSUInteger randomIndex = (NSUInteger)(arc4random() % i);
[animal removeObjectAtIndex:randomIndex];
if ([animal[randomIndex] isKindOfClass:[GWBird class]]) {
birdCount++;
} else if ([animal[randomIndex] isKindOfClass:[GWFish class]]) {
fishCount++;
}
}
// FIXME: Print a more readable result.
NSLog(@"fishCount:%d, birdCount:%d, randomRemoveNumber:%lu, [animal count]:%lu", fishCount, birdCount, (unsigned long)randomRemoveNumber, (unsigned long)[animal count]);

日程安装

  • 上午完成测试题目
  • 下午项目可行性的探讨,是否砍掉

@芦苇: BRD/MRD文档撰写指导

###产品的7问:

  1. 做什么
  2. 为谁做
  3. 市场有多大
  4. 竞争对手
  5. 时机
  6. 如何打造核心竞争力
  7. 阶段性的目标

想清楚做什么,可能做起来会容易一点。

项目可行性的探讨

@孔祥波:主界面日历方式的实现:锻炼逻辑,都是一些基础的,实现布局和代理的。可以学习 table view 的整个逻辑,datasource、delegate,

小组讨论了:几个页面和存储功能开发的分配,添加 task 到 Teambition。

@李建忠:产品核心竞争力,亮点有没有?不仅仅要学习技术,更是要学会做一个好的产品,做出来一个好的产品。

要好好想想我们项目的方向问题。

最后下周 Swift 开课,晒一下新书

Swift books

自学 iOS 开发的一些经验,是一篇充实有料常看常新的开发文章,提到了 “class-dump 从 Mach-O 文件生成 OC 头文件,有时想看看某个 App 大概是如何组织的会比较方便”。刚好最近项目想学习一下别人的APP,尝试了7-8个小时终于成功了,记录一下过程。最主要是介绍 Clutch 的文章太少,其输出路径被卡壳。

##class-dump 安装

  1. 下载地址 http://stevenygard.com/projects/class-dump/
  2. 终端中输入open /usr/bin
  3. 将解压出来的class-dump放入刚打开的目录。
  4. 更改class-dump权限 sudo chmod 777 /usr/bin/class-dump

##class-dump 用法

1
2
class-dump Name.app > class-dump.md  
class-dump -H Name.app -o folderName

第一行表示输出为一个文件方便搜索查找,第二行表示输出所以 class 到 folderName 文件夹。

解密工具 Clutch

由于 App Store 对 ipa 文件进行了加密,就有了下面的解密过程。

Clutch on GitHub:

Introducing Clutch, the fastest and most advanced dumping utility for the iPhone, iPod Touch, and iPad.

Works with all devices, iOS versions, architecture types, with most binaries.

This product is meant only for educational purposes and security research.

Compiling: Use Xcode with iOSOpenDev installed

可以直接去 Releases 下载编译好的版本,复制到 /usr/bin

1
2
3

scp ~/Downloads/Clutch root@192.168.0.X:/usr/bin

参看:iOS 使用Class-dump分析App内部实现:

Openssh,然后电脑端使用ssh连接真机(默认密码是alpine),输入命令Clutch后会看到一个App列表,找到sing在列表中的序号是3,执行命令Clutch 3,这时它就真的开始运行了,运行后的结果是将原Appstore App转换为ipa文件;最重要的是,它被解密了~

1
2
3
Clutch 

Clutch -d 3

但是在 Clutch 2.0 版目录改为:/var/mobile/Documents/Dumped/ 或 User/Documents/Dumped/,导出 ipa 即可开始 class-dump。

Clutch 2.0 Dumped folder

Update 2015-08-15: Updated for more search shortcuts.

Shortcuts Description
F1 Alfred
F2 Look up in Dash
Command-F2 Open or hide Dash
F3 Look up in EuDic
F4 Search with Google
F5 Next source in Input menu
F6 Speak selected text
Default Shortcuts Description
Control-Space Bar Change input source
Command-Space Bar Spotlight
Command-T New Tab
Shift-Command-T Reopen Closed Tab or File
Command-W Close Tab or Window
Option–Left Arrow Move the insertion point to the beginning of the previous word.
Control-A Move to the beginning of the line or paragraph.
Control-E Move to the end of a line or paragraph.

Use all F1, F2, etc. keys as standard functions keys. It‘s more efficient.

Predictive Text in OS X, esc in some apps, F5 in all apps. But hallelujahIM(哈利路亚 英文输入法) is much better with translation.

More OS X default shortcuts

13. 集合类

只要记住有这个方法或类,知道有什么用,不一定非要记住长长的名字,我们随时查看文档即可。

14. 代理

上班怎么收家里衣服:电话请家人、邻居帮忙。

MVC 为什么使用代理?

前三步:A、申明代理原型。B、申明代理变量。C、调用代理方法。

后三步:A、<>申明实现代理。B、设置代理的值。C、实现代理方法。

16. 类别、扩展与通知

Category & Extension

  • Category给原有的类扩展特有的方法。可以分解文件代码和功能

  • Extension可以扩展变量、属性,可以改写属性的读写属性。

  • 什么时候用?

BLDemo01 L16 在 ViewController.h 完成代理,非课堂上 AppDelegate.h 中。

源码保存在我的 GitHub: GeekBand-iOS-Demo

Removed FuzzyAutocomplete plugin. It made me stupid.

15. 地图与定位

地图这一节实践了一天,理一理知识点:

  • CLLocationManager and CLLocationManagerDelegate 地理事件处理和其代理方法
  • CLLocation 地理坐标
  • CLGeocoder 地理坐标化
  • MKMapView and MKMapViewDelegate 地图显示和处理相关的代理方法
  • MKAnnotationView’s protocol is MKAnnotation 自定义一个标记

Geocoding (sometimes called forward geocoding) uses a description of a location, most typically a postal address or place name, to find geographic coordinates from spatial reference data such as building polygons, land parcels, street addresses, postal codes (e.g. ZIP codes, CEDEX) and so on.

可能是时间不充足,段老师后面课程的代码风格不好。少#pragma mark 分段,少注释,if 语句嵌套的错误,命名随意。

贴一个 Apple Sample: MapCallouts

17. UITableView(一)

UITableView 和 UITableViewController 关系图

Imgur
Imgur

  • UITableView 初始化后,属性和方法
  • UITableViewDataSource and UITableViewDelegate 方法
  • section、row、cell 部分、行、细胞
  • header、footer
  • separator 分割线

20.UITableView(四)

主要是一个 table view 的 Demo。

源码保存在我的 GitHub: GeekBand-iOS-Demo

0%