- iOS 教程
- iOS - 首页
- iOS - 入门指南
- iOS - 环境设置
- iOS - Objective-C 基础
- iOS - 第一个 iPhone 应用
- iOS - 动作和出口
- iOS - 代理
- iOS - UI 元素
- iOS - 加速度计
- iOS - 通用应用程序
- iOS - 相机管理
- iOS - 位置处理
- iOS - SQLite 数据库
- iOS - 发送邮件
- iOS - 音频和视频
- iOS - 文件处理
- iOS - 访问地图
- iOS - 应用内购买
- iOS - iAd 集成
- iOS - GameKit
- iOS - 故事板
- iOS - 自动布局
- iOS - Twitter 和 Facebook
- iOS - 内存管理
- iOS - 应用程序调试
- iOS 有用资源
- iOS 快速指南
- iOS - 有用资源
- iOS - 讨论
iOS 快速指南
iOS - 入门指南
概述
iOS,之前称为 iPhone OS,是苹果公司开发的一款移动操作系统。它于 2007 年首次发布,包括 iPhone 和 iPod Touch。iPad(第一代)于 2010 年 4 月发布,iPad mini 于 2012 年 11 月发布。
iOS 设备更新频率相当高,根据经验,我们发现每年至少会发布一个版本的 iPhone 和 iPad。现在,我们有了 iPhone 5,它的前身从 iPhone、iPhone 3gs、iPhone 4、iPhone 4s 开始。同样,iPad 也从 iPad(第一代)发展到 iPad(第四代),以及一个额外的 iPad mini 版本。
iOS SDK 从 1.0 发展到 6.0。iOS 6.0 是最新的 SDK,也是 Xcode 4.5 及更高版本中唯一官方支持的版本。我们拥有丰富的苹果文档,我们可以根据我们的部署目标找到可以使用哪些方法和库。在当前版本的 Xcode 中,我们将能够在 iOS 4.3、5.0 和 6.0 的部署目标之间进行选择。
iOS 的强大功能可以通过以下一些作为设备一部分提供的功能感受到。
- 地图
- Siri
- Facebook 和 Twitter
- 多点触控
- 加速度计
- GPS
- 高端处理器
- 相机
- Safari
- 强大的 API
- 游戏中心
- 应用内购买
- 提醒事项
- 广泛的手势操作
使用 iPhone/iPad 的用户数量大幅增加。这为开发者创造了机会,可以通过为苹果的 App Store 创建 iPhone 和 iPad 应用程序来赚钱。
对于 iOS 新手,苹果设计了一个应用商店,用户可以在其中购买为其 iOS 设备开发的应用。开发者可以创建免费和付费应用到 App Store。要开发应用程序并分发到商店,开发者需要注册 iOS 开发者计划,每年费用为 99 美元,以及一台安装了 Mountain Lion 或更高版本的 Mac 以及最新的 Xcode 进行开发。
注册为苹果开发者
如果您拥有任何苹果设备,并且是一名开发者,那么 Apple ID 是必不可少的。它是免费的,因此拥有一个没有任何问题。拥有 Apple 帐户的好处如下:
访问开发工具。
全球开发者大会 (WWDC) 视频。
在收到邀请时可以加入 iOS 开发者计划团队。
要注册 Apple 帐户,请按照以下步骤操作:
步骤 1 - 点击链接 https://developer.apple.com/programs/register/ 并选择“创建 Apple ID”
步骤 2 - 提供必要的信息,页面中给出的信息不言而喻。
步骤 3 - 使用您的电子邮件验证来验证您的帐户,帐户将变为活动状态。
步骤 4 - 现在您将能够下载开发者工具,例如 Xcode(打包了 iOS 模拟器和 iOS SDK)和其他开发者资源。
苹果 iOS 开发者计划
新开发者会提出的第一个问题是——为什么要注册 iOS 开发者计划?答案很简单;苹果始终专注于为其用户提供高质量的应用程序。如果没有注册费,可能会出现垃圾应用上传的情况,这可能会给苹果的应用审核团队造成问题。
加入 iOS 开发者计划的好处如下:
在真实的 iOS 设备上运行您开发的应用程序。
将应用程序分发到应用商店。
获取开发者预览版。
加入 iOS 开发者计划的步骤如下:
步骤 1 - 要注册,请点击链接 - (https://developer.apple.com/programs/ios/).
步骤 2 - 点击显示页面中的“立即注册”。
步骤 3 - 您可以登录到您现有的 Apple 帐户(如果您有的话)或创建一个新的 Apple ID。
步骤 4 - 之后,您必须在个人帐户和公司帐户之间进行选择。如果您的团队中有多个开发者,请使用公司帐户。在个人帐户中,您无法添加成员。
步骤 5 - 输入个人信息(对于新注册的用户),您可以通过信用卡支付并激活该程序(仅接受信用卡支付)。
步骤 6 - 现在,您将能够通过在页面中选择“成员中心”选项来访问开发者资源。
步骤 7 - 在这里,您将能够执行以下操作:
创建配置文件。
管理您的团队和设备。
通过 iTunes Connect 管理应用程序到应用商店。
获取论坛和技术支持。
iOS - 环境设置
iOS - Xcode 安装
步骤 1 - 从 https://developer.apple.com/downloads/ 下载最新版本的 Xcode
步骤 2 - 双击 Xcode dmg 文件。
步骤 3 - 您将找到一个已挂载并打开的设备。
步骤 4 - 显示的窗口中将有两个项目,即 Xcode 应用程序和应用程序文件夹的快捷方式。
步骤 5 - 将 Xcode 拖到应用程序中,它将被复制到您的应用程序中。
步骤 6 - 现在 Xcode 将作为其他应用程序的一部分提供,您可以从中选择并运行。
您还可以从 Mac App Store 下载 Xcode,然后按照屏幕上提供的分步操作进行安装。
界面构建器
界面构建器是一种工具,可以轻松创建 UI 界面。您有一套丰富的 UI 元素可供使用。您只需将其拖放到您的 UI 视图中即可。我们将在接下来的页面中学习有关添加 UI 元素、为 UI 元素创建出口和动作的信息。
您在右下角有对象库,其中包含所有必要的 UI 元素。用户界面通常称为xib,这是其文件扩展名。每个 xib 都链接到相应的视图控制器。
iOS 模拟器
iOS 模拟器实际上包含两种类型的设备,即 iPhone 和 iPad 及其不同版本。iPhone 版本包括 iPhone(普通版)、iPhone Retina、iPhone 5。iPad 有 iPad 和 iPad Retina。下面显示了 iPhone 模拟器的屏幕截图。
您可以在 iOS 模拟器中模拟位置,以玩弄应用程序的纬度和经度效果。您还可以在模拟器中模拟内存警告和通话状态。您可以将模拟器用于大多数目的,但是您无法测试诸如加速度计之类的设备功能。因此,您可能始终需要一个 iOS 设备来彻底测试应用程序的所有场景。
iOS - Objective C
iOS 开发中使用的语言是 Objective C。它是一种面向对象的语言,因此对于那些有一些面向对象编程语言背景的人来说,它会很容易。
接口和实现
在 Objective C 中,声明类的文件称为接口文件,定义类的文件称为实现文件。
一个简单的接口文件MyClass.h如下所示:
@interface MyClass:NSObject { // class variable declared here } // class properties declared here // class methods and instance methods declared here @end
实现文件MyClass.m如下所示:
@implementation MyClass // class methods defined here @end
对象创建
对象创建如下所示:
MyClass *objectName = [[MyClass alloc]init] ;
方法
在 Objective C 中声明方法如下所示:
-(returnType)methodName:(typeName) variable1 :(typeName)variable2;
下面显示了一个示例。
-(void)calculateAreaForRectangleWithLength:(CGfloat)length andBreadth:(CGfloat)breadth;
您可能想知道andBreadth字符串是做什么用的;实际上它是一个可选字符串,可以帮助我们轻松地阅读和理解方法,尤其是在调用时。要在同一类中调用此方法,我们使用以下语句:
[self calculateAreaForRectangleWithLength:30 andBreadth:20];
如上所述,使用 andBreadth 可以帮助我们理解宽度为 20。self 用于指定它是一个类方法。
类方法
类方法可以直接访问,无需为类创建对象。它们没有任何变量和对象与之关联。下面显示了一个示例。
+(void)simpleClassMethod;
可以使用类名(假设类名为 MyClass)访问它,如下所示:
[MyClass simpleClassMethod];
实例方法
实例方法只能在为类创建对象后访问。内存分配给实例变量。下面显示了一个示例实例方法。
-(void)simpleInstanceMethod;
创建类对象后,可以访问它,如下所示:
MyClass *objectName = [[MyClass alloc]init] ; [objectName simpleInstanceMethod];
Objective C 中的重要数据类型
序号 | 数据类型 |
---|---|
1 | NSString 用于表示字符串。 |
2 | CGfloat 用于表示浮点值(也允许使用普通浮点数,但最好使用 CGfloat)。 |
3 | NSInteger 用于表示整数。 |
4 | BOOL 用于表示布尔值(允许使用 YES 或 NO 布尔类型)。 |
打印日志
NSLog - 用于打印语句。它将分别在发布和调试模式下打印在设备日志和调试控制台中。例如,
NSlog(@"");
控制结构
大多数控制结构与 C 和 C++ 中的相同,除了少数添加,例如 for in 语句。
属性
为了让外部类访问类,使用变量属性。例如,
@property(nonatomic , strong) NSString *myString;
访问属性
您可以使用点运算符访问属性。要访问上述属性,我们将执行以下操作。
self.myString = @"Test";
您还可以使用 set 方法,如下所示:
[self setMyString:@"Test"];
类别
类别用于向现有类添加方法。通过这种方式,我们可以为那些我们甚至没有其实现文件的类添加方法,而这些文件定义了实际的类。我们类的示例类别如下所示:
@interface MyClass(customAdditions) - (void)sampleCategoryMethod; @end @implementation MyClass(categoryAdditions) -(void)sampleCategoryMethod { NSLog(@"Just a test category"); }
数组
NSMutableArray 和 NSArray 是 Objective C 中使用的数组类。顾名思义,前者是可变的,后者是不可变的。下面显示了一个示例。
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init]; [anArray addObject:@"firstobject"]; NSArray *aImmutableArray = [[NSArray alloc] initWithObjects:@"firstObject",nil];
字典
NSMutableDictionary 和 NSDictionary 是 Objective C 中使用的字典类。顾名思义,前者是可变的,后者是不可变的。下面显示了一个示例。
NSMutableDictionary *aMutableDictionary = [[NSMutableArray alloc]init]; [aMutableDictionary setObject:@"firstobject" forKey:@"aKey"]; NSDictionary*aImmutableDictionary= [[NSDictionary alloc]initWithObjects:[NSArray arrayWithObjects: @"firstObject",nil] forKeys:[ NSArray arrayWithObjects:@"aKey"]];
iOS - 第一个 iPhone 应用
创建第一个应用
现在我们将创建一个简单的单视图应用程序(一个空白应用程序),它将在 iOS 模拟器上运行。
步骤如下所示。
步骤 1 - 打开 Xcode 并选择创建新的 Xcode 项目。
步骤 2 - 选择单视图应用程序。
步骤 3 - 输入产品名称(即应用程序的名称)、组织名称,然后是公司标识符。
步骤 4 - 确保选中使用自动引用计数,以便在资源超出范围后自动释放分配的资源。点击下一步。
步骤 5 - 选择项目的目录并选择创建。
步骤 6 - 您将看到如下所示的屏幕:
在上面的屏幕中,您将能够选择支持的方向、构建和发布设置。有一个字段部署目标,我们想要支持的设备版本,让我们选择 4.3,这是现在允许的最小部署目标。目前,这些不是必需的,让我们专注于运行应用程序。
步骤 7 - 现在,在运行按钮附近的下拉菜单中选择 iPhone 模拟器,然后选择运行。
步骤 8 - 就这样;您已成功运行了第一个应用程序。您将获得如下所示的输出:
现在让我们更改背景颜色,只是为了开始使用界面构建器。选择 ViewController.xib。在右侧选择背景选项,更改颜色并运行。
在上面的项目中,默认情况下,部署目标将设置为 iOS 6.0,并且将启用自动布局。为了确保我们的应用程序在 iOS 4.3 及更高版本的设备上运行,我们已经在创建此应用程序的开始修改了部署目标,但我们没有禁用自动布局。
要禁用自动布局,我们需要在每个 nib(即 xib 文件)的文件检查器中取消选中自动布局复选框。Xcode 项目 IDE 的各个部分如下图所示(由 Apple Xcode 4 用户文档提供)。
文件检查器位于如上所示的检查器选择器栏中,可以在其中取消选中自动布局。当您只想针对 iOS 6 设备时,可以使用自动布局。此外,如果您将部署目标提高到 iOS 6,您将能够使用许多新功能,例如 Passbook。目前,让我们将 iOS 4.3 作为部署目标。
第一个 iOS 应用程序的代码
您会发现为您的应用程序生成的五个不同的文件。它们列出如下:
- AppDelegate.h
- AppDelegate.m
- ViewController.h
- ViewController.m
- ViewController.xib
AppDelegate.h
// Header File that provides all UI related items. #import <UIKit/UIKit.h> // Forward declaration (Used when class will be defined /imported in future) @class ViewController; // Interface for Appdelegate @interface AppDelegate : UIResponder <UIApplicationDelegate> // Property window @property (strong, nonatomic) UIWindow *window; // Property Viewcontroller @property (strong, nonatomic) ViewController *viewController; //this marks end of interface @end
代码中的重要项目:
AppDelegate 继承自 UIResponder,用于处理 iOS 事件。
实现 UIApplicationDelegate 的委托方法,提供关键的应用程序事件,如完成启动、即将终止等。
UIWindow 对象用于管理和协调 iOS 设备屏幕上的各种视图。它就像所有其他视图加载的基础视图。通常,一个应用程序只有一个窗口。
UIViewController 用于处理屏幕流程。
AppDelegate.m
// Imports the class Appdelegate's interface import "AppDelegate.h" // Imports the viewcontroller to be loaded #import "ViewController.h" // Class definition starts here @implementation AppDelegate // Method to intimate us that the application launched successfully - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(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.*/ } - (void)applicationWillEnterForeground:(UIApplication *)application { /* Called as part of the transition from the background to the inactive state. Here you can undo many of the changes made on entering the background.*/ } - (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.*/ } - (void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. */ } - (void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. */ } @end
代码中的重要项目:
UIApplication 委托在此处定义。上面定义的所有方法都是 UI 应用程序委托,不包含用户定义的方法。
分配 UIWindow 对象以保存分配的应用程序。
将 UIViewController 分配为窗口的初始视图控制器。
要使窗口可见,会调用 makeKeyAndVisible 方法。
ViewController.h
#import <UIKit/UIKit.h> // Interface for class ViewController @interface ViewController : UIViewController @end
代码中的重要项目:
ViewController 类继承自 UIViewController,它为 iOS 应用程序提供了基本的视图管理模型。
ViewController.m
#import "ViewController.h" // Category, an extension of ViewController class @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
代码中的重要项目:
此处实现的两种方法在基类 UIViewController 中定义。
在 viewDidLoad 中进行初始设置,该方法在视图加载后调用。
如果出现内存警告,则调用 didReceiveMemoryWarning 方法。
iOS - 动作和出口
iOS 中的操作和出口分别称为ibActions和ibOutlets,其中ib代表界面构建器。这些与 UI 元素相关,在了解如何以可视方式实现它们之后,我们将探讨它们。
操作和出口 - 涉及的步骤
步骤 1 - 让我们使用我们的第一个 iPhone 应用程序。
步骤 2 - 从导航器部分的文件中选择 ViewController.xib 文件。
步骤 3 - 现在,您可以从窗口右侧的库窗格中选择 UI 元素,如下所示。
步骤 4 - 您可以将 UI 元素拖放到界面构建器中的视图中。
步骤 5 - 让我们向视图添加一个标签和一个圆角矩形按钮。
步骤 6 - 从位于右上角的工作区工具栏中的编辑器选择器按钮中。
选择助手编辑器按钮。
步骤 7 - 我们将在中心的编辑器区域看到两个窗口,一个是 ViewController.xib 文件,另一个是 ViewController.h。
步骤 8 - 现在,右键单击标签并选择、按住并拖动新的引用出口,如下所示。
步骤 9 - 放到 ViewController.h 中的花括号之间。如果文件中没有花括号,请在执行此操作之前添加 ViewController。您会看到如下所示的弹出窗口。
步骤 10 - 为出口键入标签名称,这里我们使用了标签 myTitleLabel。单击连接,ibOutlet 将完成。
步骤 11 - 同样,要添加操作,请右键单击圆角矩形按钮,选择触摸内部并将其拖到花括号下方。
步骤 12 - 放下它并将其命名为 setTitleLabel。
步骤 13 - 选择 ViewController.m 文件,您会找到如下所示的方法。
-(IBAction) setTitleLabel:(id)sender { }
步骤 14 - 在上述方法内部添加如下所示的语句。
[myTitleLabel setText:@"Hello"];
步骤 15 - 现在让我们通过选择运行按钮来运行程序。您将看到以下输出。
步骤 16 - 现在单击按钮。
步骤 17 - 我们创建的标签已通过按钮上的操作更改。
步骤 18 - 从上面的示例中,我们可以得出结论,IBOutlet 创建了对 UIElement 的引用(此处用于 UILabel)。同样,IBAction 将 UIButton 与一个方法链接起来,该方法在事件触摸内部时被调用。
步骤 19 - 您可以通过在创建操作时选择不同的事件来玩转操作。
iOS - 代理
委托示例
假设对象 A 调用对象 B 来执行操作。操作完成后,对象 A 应该知道 B 已完成任务并采取必要的操作。这是借助委托实现的。
上面示例中的关键概念是:
A 是 B 的委托对象。
B 将拥有 A 的引用。
A 将实现 B 的委托方法。
B 将通过委托方法通知 A。
创建委托的步骤
步骤 1 - 首先,创建一个单视图应用程序。
步骤 2 - 然后选择文件→新建→文件…
步骤 3 - 然后选择 Objective C 类并点击下一步。
步骤 4 - 为类命名,例如 SampleProtocol,子类为 NSObject,如下所示。
步骤 5 - 然后选择创建。
步骤 6 - 向 SampleProtocol.h 文件添加协议,更新后的代码如下所示:
#import <Foundation/Foundation.h> // Protocol definition starts here @protocol SampleProtocolDelegate <NSObject> @required - (void) processCompleted; @end // Protocol Definition ends here @interface SampleProtocol : NSObject { // Delegate to respond back id <SampleProtocolDelegate> _delegate; } @property (nonatomic,strong) id delegate; -(void)startSampleProcess; // Instance method @end
步骤 7 - 通过更新 SampleProtocol.m 文件来实现实例方法,如下所示。
#import "SampleProtocol.h" @implementation SampleProtocol -(void)startSampleProcess { [NSTimer scheduledTimerWithTimeInterval:3.0 target:self.delegate selector:@selector(processCompleted) userInfo:nil repeats:NO]; } @end
步骤 8 - 通过将标签从对象库拖到 UIView 中,在 ViewController.xib 中添加一个 UILabel,如下所示。
步骤 9 - 为标签创建 IBOutlet 并将其命名为 myLabel,并更新代码以在 ViewController.h 中采用 SampleProtocolDelegate。
#import <UIKit/UIKit.h> #import "SampleProtocol.h" @interface ViewController : UIViewController<SampleProtocolDelegate> { IBOutlet UILabel *myLabel; } @end
步骤 10 实现委托方法,创建 SampleProtocol 的对象并调用 startSampleProcess 方法。更新后的 ViewController.m 文件如下所示:
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; SampleProtocol *sampleProtocol = [[SampleProtocol alloc]init]; sampleProtocol.delegate = self; [myLabel setText:@"Processing..."]; [sampleProtocol startSampleProcess]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Sample protocol delegate -(void)processCompleted { [myLabel setText:@"Process Completed"]; } @end
步骤 11 我们将看到如下所示的输出。最初,标签显示“处理中...”,一旦 SampleProtocol 对象调用委托方法,它就会更新。
iOS - UI 元素
什么是 UI 元素?
UI 元素是我们可以在应用程序中看到的视觉元素。其中一些元素响应用户交互,例如按钮、文本字段,而另一些则提供信息,例如图像、标签。
如何添加 UI 元素?
我们可以在代码中以及借助界面构建器添加 UI 元素。根据需要,我们可以使用其中任何一个。
我们的重点
我们将更多地关注在应用程序中通过代码添加 UI 元素。使用界面构建器很简单且直观,我们只需要拖放 UI 元素即可。
我们的方法
我们将创建一个简单的 iOS 应用程序,并使用它来解释一些 UI 元素。
步骤 1 - 创建一个基于视图的应用程序,就像我们在第一个 iOS 应用程序中所做的那样。
步骤 2 - 我们将只更新 ViewController.h 和 ViewController.m 文件。
步骤 3 - 然后,我们向 ViewController.m 文件添加一个特定于创建 UI 元素的方法。
步骤 4 - 我们将在 viewDidLoad 方法中调用此方法。
步骤 5 - 代码中的重要代码行已在这些代码行上方的单行注释中进行了说明。
UI 元素列表
下面解释了 UI 特定元素及其相关功能:
序号 | UI 特定元素 |
---|---|
1 | 文本字段
它是一个 UI 元素,使应用程序能够获取用户输入。 |
2 | 输入类型 - 文本字段
我们可以通过使用 UITextField 的 keyboard 属性来设置用户可以使用键盘输入的类型。 |
3 | 按钮
它用于处理用户操作。 |
4 | 标签
它用于显示静态内容。 |
5 | 工具栏
如果我们想根据当前视图操作某些内容,则可以使用它。 |
6 | 状态栏
它显示设备的关键信息。 |
7 | 导航栏
它包含导航控制器的导航按钮,导航控制器是一个视图控制器的堆栈,可以进行推入和弹出操作。 |
8 | 标签栏
它通常用于在同一视图内的各种子任务、视图或模型之间切换。 |
9 | 图像视图
它用于显示简单的图像或图像序列。 |
10 | 滚动视图
它用于显示超出屏幕区域的内容。 |
11 | 表格视图
它用于以多行和多节的形式显示可滚动的列表数据。 |
12 | 分割视图
它用于显示两个窗格,其中主窗格控制详细信息窗格上的信息。 |
13 | 文本视图
它用于显示可滚动的文本信息列表,可以选择进行编辑。 |
14 | 视图转换
它解释了视图之间各种视图转换。 |
15 | 拾取器
它用于显示从列表中选择特定数据。 |
16 | 开关
它用作操作的禁用和启用。 |
17 | 滑块
它允许用户在允许值的范围内调整值或过程。 |
18 | 警报
它用于向用户提供重要信息。 |
19 | 图标
它是用于操作或描述与应用程序相关内容的图像表示。 |
iOS - 加速度计
加速计用于检测设备在三个方向(x、y 和 z)上的位置变化。我们可以知道设备相对于地面的当前位置。要测试此示例,您需要在**设备**上运行它,并且它在模拟器上不起作用。
加速计 - 涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 在**ViewController.xib**中添加三个标签,并创建名为 xlabel、ylabel 和 zlabel 的 ibOutlets。
**步骤 3** - 如下更新 ViewController.h -
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<UIAccelerometerDelegate> { IBOutlet UILabel *xlabel; IBOutlet UILabel *ylabel; IBOutlet UILabel *zlabel; } @end
**步骤 4** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[UIAccelerometer sharedAccelerometer]setDelegate:self]; //Do any additional setup after loading the view,typically from a nib } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration { [xlabel setText:[NSString stringWithFormat:@"%f",acceleration.x]]; [ylabel setText:[NSString stringWithFormat:@"%f",acceleration.y]]; [zlabel setText:[NSString stringWithFormat:@"%f",acceleration.z]]; } @end
输出
当我们在**iPhone**设备上运行应用程序时,我们将获得以下输出 -
iOS - 通用应用程序
通用应用程序是在单个二进制文件中同时为 iPhone 和 iPad 设计的应用程序。通用应用程序允许代码重用和快速更新。
通用应用程序 - 涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 将文件名**ViewController.xib**文件更改为**ViewController_iPhone.xib**,如下所示,位于右侧的文件检查器中。
**步骤 3** - 选择文件→新建→文件...然后选择子部分**“用户界面”**并选择**视图**。点击下一步。
**步骤 4** - 选择设备系列为**iPad**,然后点击下一步。
**步骤 5** - 将文件保存为**ViewController_iPad.xib**并选择创建。
**步骤 6** - 在**ViewController_iPhone.xib**和**ViewController_iPad.xib**中屏幕中央添加一个标签。
**步骤 7** - 在**ViewController_iPad.xib**中,选择**身份检查器**并将自定义类设置为**ViewController**。
**步骤 8** - 如下更新 AppDelegate.m 中的 application:DidFinishLaunching:withOptions 方法 -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil]; } else { self.viewController = [[ViewController alloc] initWithNibName: @"ViewController_iPad" bundle:nil]; } self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
**步骤 9** - 如下所示将项目摘要中的设备更新为**通用** -
输出
当我们运行应用程序时,我们将获得以下输出 -
当我们在 iPad 模拟器上运行应用程序时,我们将获得以下输出 -
iOS - 相机管理
摄像头是移动设备中常见的特性之一。我们可以使用摄像头拍照并在我们的应用程序中使用它,而且操作也相当简单。
摄像头管理 - 涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 在**ViewController.xib**中添加一个**按钮**,并为该按钮创建 IBAction。
**步骤 3** - 添加一个**图像视图**并创建名为 imageView 的 IBOutlet。
**步骤 4** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<UIImagePickerControllerDelegate> { UIImagePickerController *imagePicker; IBOutlet UIImageView *imageView; } - (IBAction)showCamera:(id)sender; @end
**步骤 5** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)showCamera:(id)sender { imagePicker.allowsEditing = YES; if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) { imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; } else { imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; } [self presentModalViewController:imagePicker animated:YES]; } -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage]; if (image == nil) { image = [info objectForKey:UIImagePickerControllerOriginalImage]; } imageView.image = image; } -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [self dismissModalViewControllerAnimated:YES]; } @end
输出
当我们运行应用程序并点击显示摄像头按钮时,我们将获得以下输出 -
拍摄照片后,我们可以编辑照片,即移动和缩放,如下所示 -
iOS - 位置处理
我们可以轻松地找到用户在 iOS 中的当前位置,前提是用户允许应用程序在核心位置框架的帮助下访问信息。
位置处理 - 涉及的步骤
**步骤 1** - 创建一个简单的基于视图的应用程序。
**步骤 2** - 选择您的项目文件,然后选择目标,然后添加 CoreLocation.framework,如下所示 -
**步骤 3** - 在**ViewController.xib**中添加两个标签,并分别创建名为**latitudeLabel**和**longitudeLabel**的 ibOutlets。
**步骤 4** - 通过选择文件→新建→文件...→选择**Objective C 类**并点击下一步创建一个新文件。
**步骤 5** - 将类命名为**LocationHandler**,并将**“子类”**设置为 NSObject。
**步骤 6** - 选择创建。
**步骤 7** - 如下更新**LocationHandler.h** -
#import <Foundation/Foundation.h> #import <CoreLocation/CoreLocation.h> @protocol LocationHandlerDelegate <NSObject> @required -(void) didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation; @end @interface LocationHandler : NSObject<CLLocationManagerDelegate> { CLLocationManager *locationManager; } @property(nonatomic,strong) id<LocationHandlerDelegate> delegate; +(id)getSharedInstance; -(void)startUpdating; -(void) stopUpdating; @end
**步骤 8** - 如下更新**LocationHandler.m** -
#import "LocationHandler.h" static LocationHandler *DefaultManager = nil; @interface LocationHandler() -(void)initiate; @end @implementation LocationHandler +(id)getSharedInstance{ if (!DefaultManager) { DefaultManager = [[self allocWithZone:NULL]init]; [DefaultManager initiate]; } return DefaultManager; } -(void)initiate { locationManager = [[CLLocationManager alloc]init]; locationManager.delegate = self; } -(void)startUpdating{ [locationManager startUpdatingLocation]; } -(void) stopUpdating { [locationManager stopUpdatingLocation]; } -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { if ([self.delegate respondsToSelector:@selector (didUpdateToLocation:fromLocation:)]) { [self.delegate didUpdateToLocation:oldLocation fromLocation:newLocation]; } } @end
**步骤 9** - 如下更新**ViewController.h**,我们已在其中实现了**LocationHandler 委托**并创建了两个 ibOutlets -
#import <UIKit/UIKit.h> #import "LocationHandler.h" @interface ViewController : UIViewController<LocationHandlerDelegate> { IBOutlet UILabel *latitudeLabel; IBOutlet UILabel *longitudeLabel; } @end
**步骤 10** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[LocationHandler getSharedInstance]setDelegate:self]; [[LocationHandler getSharedInstance]startUpdating]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { [latitudeLabel setText:[NSString stringWithFormat: @"Latitude: %f",newLocation.coordinate.latitude]]; [longitudeLabel setText:[NSString stringWithFormat: @"Longitude: %f",newLocation.coordinate.longitude]]; } @end
输出
当我们运行应用程序时,我们将获得以下输出 -
iOS - SQLite 数据库
SQLite 可用于 iOS 处理数据。它使用 sqlite 查询,这使得那些了解 SQL 的人更容易使用。
涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 选择您的项目文件,然后选择目标,然后在选择框架中添加**libsqlite3.dylib**库。
**步骤 3** - 通过选择文件→新建→文件...→选择**Objective C 类**并点击下一步创建一个新文件。
**步骤 4** - 将类命名为**DBManager**,并将**“子类”**设置为 NSObject。
**步骤 5** - 选择创建。
**步骤 6** - 如下更新**DBManager.h** -
#import <Foundation/Foundation.h> #import <sqlite3.h> @interface DBManager : NSObject { NSString *databasePath; } +(DBManager*)getSharedInstance; -(BOOL)createDB; -(BOOL) saveData:(NSString*)registerNumber name:(NSString*)name department:(NSString*)department year:(NSString*)year; -(NSArray*) findByRegisterNumber:(NSString*)registerNumber; @end
**步骤 7** - 如下更新**DBManager.m** -
#import "DBManager.h" static DBManager *sharedInstance = nil; static sqlite3 *database = nil; static sqlite3_stmt *statement = nil; @implementation DBManager +(DBManager*)getSharedInstance { if (!sharedInstance) { sharedInstance = [[super allocWithZone:NULL]init]; [sharedInstance createDB]; } return sharedInstance; } -(BOOL)createDB { NSString *docsDir; NSArray *dirPaths; // Get the documents directory dirPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); docsDir = dirPaths[0]; // Build the path to the database file databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"student.db"]]; BOOL isSuccess = YES; NSFileManager *filemgr = [NSFileManager defaultManager]; if ([filemgr fileExistsAtPath: databasePath ] == NO) { const char *dbpath = [databasePath UTF8String]; if (sqlite3_open(dbpath, &database) == SQLITE_OK) { char *errMsg; const char *sql_stmt = "create table if not exists studentsDetail (regno integer primary key, name text, department text, year text)"; if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) { isSuccess = NO; NSLog(@"Failed to create table"); } sqlite3_close(database); return isSuccess; } else { isSuccess = NO; NSLog(@"Failed to open/create database"); } } return isSuccess; } - (BOOL) saveData:(NSString*)registerNumber name:(NSString*)name department:(NSString*)department year:(NSString*)year; { const char *dbpath = [databasePath UTF8String]; if (sqlite3_open(dbpath, &database) == SQLITE_OK) { NSString *insertSQL = [NSString stringWithFormat:@"insert into studentsDetail (regno,name, department, year) values (\"%d\",\"%@\", \"%@\", \"%@\")",[registerNumber integerValue], name, department, year]; const char *insert_stmt = [insertSQL UTF8String]; sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL); if (sqlite3_step(statement) == SQLITE_DONE) { return YES; } else { return NO; } sqlite3_reset(statement); } return NO; } - (NSArray*) findByRegisterNumber:(NSString*)registerNumber { const char *dbpath = [databasePath UTF8String]; if (sqlite3_open(dbpath, &database) == SQLITE_OK) { NSString *querySQL = [NSString stringWithFormat: @"select name, department, year from studentsDetail where regno=\"%@\"",registerNumber]; const char *query_stmt = [querySQL UTF8String]; NSMutableArray *resultArray = [[NSMutableArray alloc]init]; if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK) { if (sqlite3_step(statement) == SQLITE_ROW) { NSString *name = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)]; [resultArray addObject:name]; NSString *department = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 1)]; [resultArray addObject:department]; NSString *year = [[NSString alloc]initWithUTF8String: (const char *) sqlite3_column_text(statement, 2)]; [resultArray addObject:year]; return resultArray; } else { NSLog(@"Not found"); return nil; } sqlite3_reset(statement); } } return nil; }
**步骤 8** - 如下更新**ViewController.xib**文件 -
**步骤 9** - 为上述文本字段创建 IBOutlets。
**步骤 10** - 为上述按钮创建 IBAction。
**步骤 11** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> #import "DBManager.h" @interface ViewController : UIViewController<UITextFieldDelegate> { IBOutlet UITextField *regNoTextField; IBOutlet UITextField *nameTextField; IBOutlet UITextField *departmentTextField; IBOutlet UITextField *yearTextField; IBOutlet UITextField *findByRegisterNumberTextField; IBOutlet UIScrollView *myScrollView; } -(IBAction)saveData:(id)sender; -(IBAction)findData:(id)sender; @end
**步骤 12** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *) nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(IBAction)saveData:(id)sender { BOOL success = NO; NSString *alertString = @"Data Insertion failed"; if (regNoTextField.text.length>0 &&nameTextField.text.length>0 && departmentTextField.text.length>0 &&yearTextField.text.length>0 ) { success = [[DBManager getSharedInstance]saveData: regNoTextField.text name:nameTextField.text department: departmentTextField.text year:yearTextField.text]; } else { alertString = @"Enter all fields"; } if (success == NO) { UIAlertView *alert = [[UIAlertView alloc]initWithTitle: alertString message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } } -(IBAction)findData:(id)sender { NSArray *data = [[DBManager getSharedInstance]findByRegisterNumber: findByRegisterNumberTextField.text]; if (data == nil) { UIAlertView *alert = [[UIAlertView alloc]initWithTitle: @"Data not found" message:nil delegate:nil cancelButtonTitle: @"OK" otherButtonTitles:nil]; [alert show]; regNoTextField.text = @""; nameTextField.text =@""; departmentTextField.text = @""; yearTextField.text =@""; } else { regNoTextField.text = findByRegisterNumberTextField.text; nameTextField.text =[data objectAtIndex:0]; departmentTextField.text = [data objectAtIndex:1]; yearTextField.text =[data objectAtIndex:2]; } } #pragma mark - Text field delegate -(void)textFieldDidBeginEditing:(UITextField *)textField { [myScrollView setFrame:CGRectMake(10, 50, 300, 200)]; [myScrollView setContentSize:CGSizeMake(300, 350)]; } -(void)textFieldDidEndEditing:(UITextField *)textField { [myScrollView setFrame:CGRectMake(10, 50, 300, 350)]; } -(BOOL) textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } @end
输出
当我们运行应用程序时,我们将获得以下输出,我们可以在其中添加和查找学生详细信息 -
iOS - 发送邮件
我们可以使用 iOS 设备的电子邮件应用程序发送电子邮件。
涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 选择您的项目文件,然后选择目标,然后添加**MessageUI.framework**。
**步骤 3** - 在**ViewController.xib**中添加一个按钮,并创建一个用于发送电子邮件的操作。
**步骤 4** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> #import <MessageUI/MessageUI.h> @interface ViewController : UIViewController<MFMailComposeViewControllerDelegate> { MFMailComposeViewController *mailComposer; } -(IBAction)sendMail:(id)sender; @end
**步骤 5** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)sendMail:(id)sender { mailComposer = [[MFMailComposeViewController alloc]init]; mailComposer.mailComposeDelegate = self; [mailComposer setSubject:@"Test mail"]; [mailComposer setMessageBody:@"Testing message for the test mail" isHTML:NO]; [self presentModalViewController:mailComposer animated:YES]; } #pragma mark - mail compose delegate -(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{ if (result) { NSLog(@"Result : %d",result); } if (error) { NSLog(@"Error : %@",error); } [self dismissModalViewControllerAnimated:YES]; } @end
输出
当我们运行应用程序时,我们将获得以下输出 -
点击发送电子邮件,我们将获得以下输出 -
iOS - 音频和视频
音频和视频在最新的设备中非常常见。它分别在 iOS 中通过**AVFoundation.framework**和**MediaPlayer.framework**的支持下实现。
涉及的步骤
**步骤 1** - 创建一个简单的**基于视图的应用程序**。
**步骤 2** - 选择您的项目文件,选择目标,然后我们应该添加**AVFoundation.framework**和**MediaPlayer.framework**。
**步骤 3** - 在 ViewController.xib 中添加两个按钮,并分别创建一个用于播放音频和视频的操作。
**步骤 4** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> #import <MediaPlayer/MediaPlayer.h> @interface ViewController : UIViewController { AVAudioPlayer *audioPlayer; MPMoviePlayerViewController *moviePlayer; } -(IBAction)playAudio:(id)sender; -(IBAction)playVideo:(id)sender; @end
**步骤 5** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(IBAction)playAudio:(id)sender { NSString *path = [[NSBundle mainBundle] pathForResource:@"audioTest" ofType:@"mp3"]; audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL: [NSURL fileURLWithPath:path] error:NULL]; [audioPlayer play]; } -(IBAction)playVideo:(id)sender { NSString *path = [[NSBundle mainBundle]pathForResource: @"videoTest" ofType:@"mov"]; moviePlayer = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL fileURLWithPath:path]]; [self presentModalViewController:moviePlayer animated:NO]; } @end
注意
我们需要添加音频和视频文件以确保我们获得预期的输出。
输出
当我们运行应用程序时,我们将获得以下输出 -
当我们点击播放视频时,我们将获得如下所示的输出 -
当我们点击播放音频时,您将听到音频。
iOS - 文件处理
文件处理无法通过应用程序直观地解释,因此下面解释了用于处理文件的关键方法。请注意,应用程序包只有读取权限,我们无法修改文件。无论如何,您可以修改应用程序的文档目录。
文件处理中使用的方法
下面讨论了用于**访问**和**操作**文件的方法。在这里,我们必须将 FilePath1、FilePath2 和 FilePath 字符串替换为我们所需的完整文件路径,以获得所需的 action。
检查路径是否存在文件
NSFileManager *fileManager = [NSFileManager defaultManager]; //Get documents directory NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectoryPath = [directoryPaths objectAtIndex:0]; if ([fileManager fileExistsAtPath:@""]==YES) { NSLog(@"File exists"); }
比较两个文件内容
if ([fileManager contentsEqualAtPath:@"FilePath1" andPath:@" FilePath2"]) { NSLog(@"Same content"); }
检查是否可写、可读和可执行
if ([fileManager isWritableFileAtPath:@"FilePath"]) { NSLog(@"isWritable"); } if ([fileManager isReadableFileAtPath:@"FilePath"]) { NSLog(@"isReadable"); } if ( [fileManager isExecutableFileAtPath:@"FilePath"]) { NSLog(@"is Executable"); }
移动文件
if([fileManager moveItemAtPath:@"FilePath1" toPath:@"FilePath2" error:NULL]) { NSLog(@"Moved successfully"); }
复制文件
if ([fileManager copyItemAtPath:@"FilePath1" toPath:@"FilePath2" error:NULL]) { NSLog(@"Copied successfully"); }
删除文件
if ([fileManager removeItemAtPath:@"FilePath" error:NULL]) { NSLog(@"Removed successfully"); }
读取文件
NSData *data = [fileManager contentsAtPath:@"Path"];
写入文件
[fileManager createFileAtPath:@"" contents:data attributes:nil];
iOS - 访问地图
地图始终有助于我们找到地点。地图通过 MapKit 框架集成到 iOS 中。
涉及的步骤
**步骤 1** - 创建一个简单的基于视图的应用程序。
**步骤 2** - 选择您的项目文件,然后选择目标,然后添加 MapKit.framework。
**步骤 3** - 我们还应该添加 Corelocation.framework。
**步骤 4** - 将 MapView 添加到 ViewController.xib 并创建一个 ibOutlet 并将其命名为 mapView。
**步骤 5** - 通过选择文件→新建→文件...→选择 Objective C 类并点击下一步创建一个新文件。
**步骤 6** - 将类命名为 MapAnnotation,并将“子类”设置为 NSObject。
**步骤 7** - 选择创建。
**步骤 8** - 如下更新 MapAnnotation.h -
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MapAnnotation : NSObject<MKAnnotation> @property (nonatomic, strong) NSString *title; @property (nonatomic, readwrite) CLLocationCoordinate2D coordinate; - (id)initWithTitle:(NSString *)title andCoordinate: (CLLocationCoordinate2D)coordinate2d; @end
**步骤 9** - 如下更新**MapAnnotation.m** -
#import "MapAnnotation.h" @implementation MapAnnotation -(id)initWithTitle:(NSString *)title andCoordinate: (CLLocationCoordinate2D)coordinate2d { self.title = title; self.coordinate =coordinate2d; return self; } @end
**步骤 10** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController : UIViewController<MKMapViewDelegate> { MKMapView *mapView; } @end
**步骤 11** - 如下更新**ViewController.m** -
#import "ViewController.h" #import "MapAnnotation.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; mapView = [[MKMapView alloc]initWithFrame: CGRectMake(10, 100, 300, 300)]; mapView.delegate = self; mapView.centerCoordinate = CLLocationCoordinate2DMake(37.32, -122.03); mapView.mapType = MKMapTypeHybrid; CLLocationCoordinate2D location; location.latitude = (double) 37.332768; location.longitude = (double) -122.030039; // Add the annotation to our map view MapAnnotation *newAnnotation = [[MapAnnotation alloc] initWithTitle:@"Apple Head quaters" andCoordinate:location]; [mapView addAnnotation:newAnnotation]; CLLocationCoordinate2D location2; location2.latitude = (double) 37.35239; location2.longitude = (double) -122.025919; MapAnnotation *newAnnotation2 = [[MapAnnotation alloc] initWithTitle:@"Test annotation" andCoordinate:location2]; [mapView addAnnotation:newAnnotation2]; [self.view addSubview:mapView]; } // When a map annotation point is added, zoom to it (1500 range) - (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views { MKAnnotationView *annotationView = [views objectAtIndex:0]; id <MKAnnotation> mp = [annotationView annotation]; MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance ([mp coordinate], 1500, 1500); [mv setRegion:region animated:YES]; [mv selectAnnotation:mp animated:YES]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
输出
当我们运行应用程序时,我们将获得如下所示的输出 -
当我们向上滚动地图时,我们将获得如下所示的输出 -
iOS - 应用内购买
应用内购买用于购买应用程序的附加内容或升级功能。
涉及的步骤
**步骤 1** - 在 iTunes Connect 中,确保您拥有**唯一的 App ID**,并且当我们创建应用程序时,使用**bundle ID**更新,并在 Xcode 中使用相应的配置文件进行代码签名。
**步骤 2** - 创建一个新的应用程序并更新应用程序信息。您可以在 Apple 的**添加新应用程序**文档中了解更多相关信息。
**步骤 3** - 在应用程序页面上的**管理应用内购买**中为应用内购买添加新产品。
**步骤 4** - 确保您已为您的应用程序设置了银行详细信息。这需要为**应用内购买**设置才能正常工作。此外,使用 iTunes Connect 页面上的**管理用户**选项创建一个测试用户帐户。
**步骤 5** - 下一步与处理代码和为我们的应用内购买创建 UI 相关。
**步骤 6** - 创建一个**单视图应用程序**,并将 bundle 标识符输入为 iTunes Connect 中指定的标识符。
**步骤 7** - 如下所示更新**ViewController.xib** -
**步骤 8** - 为三个标签和按钮创建**IBOutlets**,分别命名为 productTitleLabel、productDescriptionLabel、productPriceLabel 和 purchaseButton。
**步骤 9** - 选择您的项目文件,然后选择目标,然后添加**StoreKit.framework**。
**步骤 10** - 如下更新**ViewController.h** -
#import <UIKit/UIKit.h> #import <StoreKit/StoreKit.h> @interface ViewController : UIViewController< SKProductsRequestDelegate,SKPaymentTransactionObserver> { SKProductsRequest *productsRequest; NSArray *validProducts; UIActivityIndicatorView *activityIndicatorView; IBOutlet UILabel *productTitleLabel; IBOutlet UILabel *productDescriptionLabel; IBOutlet UILabel *productPriceLabel; IBOutlet UIButton *purchaseButton; } - (void)fetchAvailableProducts; - (BOOL)canMakePurchases; - (void)purchaseMyProduct:(SKProduct*)product; - (IBAction)purchase:(id)sender; @end
**步骤 11** - 如下更新**ViewController.m** -
#import "ViewController.h" #define kTutorialPointProductID @"com.tutorialPoints.testApp.testProduct" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Adding activity indicator activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; activityIndicatorView.center = self.view.center; [activityIndicatorView hidesWhenStopped]; [self.view addSubview:activityIndicatorView]; [activityIndicatorView startAnimating]; //Hide purchase button initially purchaseButton.hidden = YES; [self fetchAvailableProducts]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)fetchAvailableProducts { NSSet *productIdentifiers = [NSSet setWithObjects:kTutorialPointProductID,nil]; productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; productsRequest.delegate = self; [productsRequest start]; } - (BOOL)canMakePurchases { return [SKPaymentQueue canMakePayments]; } - (void)purchaseMyProduct:(SKProduct*)product { if ([self canMakePurchases]) { SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } else { UIAlertView *alertView = [[UIAlertView alloc]initWithTitle: @"Purchases are disabled in your device" message:nil delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alertView show]; } } -(IBAction)purchase:(id)sender { [self purchaseMyProduct:[validProducts objectAtIndex:0]]; purchaseButton.enabled = NO; } #pragma mark StoreKit Delegate -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchasing: NSLog(@"Purchasing"); break; case SKPaymentTransactionStatePurchased: if ([transaction.payment.productIdentifier isEqualToString:kTutorialPointProductID]) { NSLog(@"Purchased "); UIAlertView *alertView = [[UIAlertView alloc]initWithTitle: @"Purchase is completed succesfully" message:nil delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alertView show]; } [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; case SKPaymentTransactionStateRestored: NSLog(@"Restored "); [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; case SKPaymentTransactionStateFailed: NSLog(@"Purchase failed "); break default: break; } } } -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { SKProduct *validProduct = nil; int count = [response.products count]; if (count>0) { validProducts = response.products; validProduct = [response.products objectAtIndex:0]; if ([validProduct.productIdentifier isEqualToString:kTutorialPointProductID]) { [productTitleLabel setText:[NSString stringWithFormat: @"Product Title: %@",validProduct.localizedTitle]]; [productDescriptionLabel setText:[NSString stringWithFormat: @"Product Desc: %@",validProduct.localizedDescription]]; [productPriceLabel setText:[NSString stringWithFormat: @"Product Price: %@",validProduct.price]]; } } else { UIAlertView *tmp = [[UIAlertView alloc] initWithTitle:@"Not Available" message:@"No products to purchase" delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok", nil]; [tmp show]; } [activityIndicatorView stopAnimating]; purchaseButton.hidden = NO; } @end
注意
您必须将 kTutorialPointProductID 更新为您为应用内购买创建的产品 ID。您可以通过更新 fetchAvailableProducts 中的 productIdentifiers 的 NSSet 来添加多个产品。类似地,处理您添加的产品 ID 的购买相关操作。
输出
当我们运行应用程序时,我们将获得以下输出 -
确保您已在设置屏幕中退出帐户。点击“发起购买”后,选择“使用现有 Apple ID”。输入您的有效测试帐户用户名和密码。几秒钟后,您将看到以下警报。
一旦您的产品成功购买,您将收到以下警报。您可以在更新应用程序功能的相关代码中看到我们显示此警报的位置。
iOS - iAd 集成
iAd 用于显示广告,由苹果服务器提供。iAd 有助于我们从 iOS 应用程序中获得收入。
iAd 集成 – 涉及的步骤
**步骤 1** - 创建一个简单的基于视图的应用程序。
步骤 2 - 选择您的项目文件,然后选择目标,然后在选择框架中添加 iAd.framework。
**步骤 3** - 如下更新 ViewController.h -
#import <UIKit/UIKit.h> #import <iAd/iAd.h> @interface ViewController : UIViewController<ADBannerViewDelegate> { ADBannerView *bannerView; } @end
**步骤 4** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; bannerView = [[ADBannerView alloc]initWithFrame: CGRectMake(0, 0, 320, 50)]; // Optional to set background color to clear color [bannerView setBackgroundColor:[UIColor clearColor]]; [self.view addSubview: bannerView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - AdViewDelegates -(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error { NSLog(@"Error loading"); } -(void)bannerViewDidLoadAd:(ADBannerView *)banner { NSLog(@"Ad loaded"); } -(void)bannerViewWillLoadAd:(ADBannerView *)banner { NSLog(@"Ad will load"); } -(void)bannerViewActionDidFinish:(ADBannerView *)banner { NSLog(@"Ad did finish"); } @end
输出
当我们运行应用程序时,我们将获得以下输出 -
iOS - GameKit
GameKit 是一个框架,它为 iOS 应用程序提供排行榜、成就和更多功能。在本教程中,我们将解释添加排行榜和更新分数的步骤。
涉及的步骤
**步骤 1** - 在 iTunes Connect 中,确保您拥有**唯一的 App ID**,并且当我们创建应用程序时,使用**bundle ID**更新,并在 Xcode 中使用相应的配置文件进行代码签名。
步骤 2 - 创建一个新的应用程序并更新应用程序信息。您可以在 apple-add new apps 文档中了解更多相关信息。
步骤 3 - 在应用程序页面上的管理游戏中心中设置排行榜,在其中添加一个排行榜并提供排行榜 ID和分数类型。在这里,我们将排行榜 ID 设置为 tutorialsPoint。
步骤 4 - 接下来的步骤与处理代码和为我们的应用程序创建 UI 相关。
步骤 5 - 创建一个单视图应用程序,并输入bundle identifier,它是iTunes Connect中指定的标识符。
步骤 6 - 按如下所示更新 ViewController.xib -
步骤 7 - 选择您的项目文件,然后选择目标,然后添加GameKit.framework。
步骤 8 - 为我们添加的按钮创建IBActions。
步骤 9 - 按如下所示更新ViewController.h文件 -
#import <UIKit/UIKit.h> #import <GameKit/GameKit.h> @interface ViewController : UIViewController <GKLeaderboardViewControllerDelegate> -(IBAction)updateScore:(id)sender; -(IBAction)showLeaderBoard:(id)sender; @end
**步骤 10** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; if([GKLocalPlayer localPlayer].authenticated == NO) { [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) { NSLog(@"Error%@",error); }]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void) updateScore: (int64_t) score forLeaderboardID: (NSString*) category { GKScore *scoreObj = [[GKScore alloc] initWithCategory:category]; scoreObj.value = score; scoreObj.context = 0; [scoreObj reportScoreWithCompletionHandler:^(NSError *error) { // Completion code can be added here UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Score Updated Succesfully" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; }]; } -(IBAction)updateScore:(id)sender { [self updateScore:200 forLeaderboardID:@"tutorialsPoint"]; } -(IBAction)showLeaderBoard:(id)sender { GKLeaderboardViewController *leaderboardViewController = [[GKLeaderboardViewController alloc] init]; leaderboardViewController.leaderboardDelegate = self; [self presentModalViewController: leaderboardViewController animated:YES]; } #pragma mark - Gamekit delegates - (void)leaderboardViewControllerDidFinish: (GKLeaderboardViewController *)viewController { [self dismissModalViewControllerAnimated:YES]; } @end
输出
当我们运行应用程序时,我们将获得以下输出 -
当我们点击“显示排行榜”时,我们会得到一个类似于以下内容的屏幕 -
当我们点击“更新分数”时,分数将更新到我们的排行榜,并且我们会收到如下所示的警报 -
iOS - 故事板
故事板在 iOS 5 中引入。当我们使用故事板时,我们的部署目标应为 5.0 或更高。故事板帮助我们创建应用程序的所有屏幕,并在一个界面 MainStoryboard.storyboard 下互连屏幕。它还有助于减少推送/呈现视图控制器的编码。
涉及的步骤
步骤 1 - 创建一个单视图应用程序,并确保在创建应用程序时选中故事板复选框。
步骤 2 - 选择MainStoryboard.storyboard,您可以在其中找到单视图控制器。再添加一个视图控制器,并按如下所示更新视图控制器。
步骤 3 - 现在让我们连接这两个视图控制器。右键单击“显示模态”按钮,并将其拖到左侧视图控制器中的右侧视图控制器,如下所示。
步骤 4 - 从显示的三个选项中选择模态,如下所示。
步骤 5 - 按如下所示更新ViewController.h -
#import <UIKit/UIKit.h> @interface ViewController : UIViewController -(IBAction)done:(UIStoryboardSegue *)seque; @end
步骤 6 - 按如下所示更新ViewController.m -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(IBAction)done:(UIStoryboardSegue *)seque { [self.navigationController popViewControllerAnimated:YES]; } @end
步骤 7 - 选择 MainStoryboard.storyboard,然后右键单击右侧视图控制器中的“退出”按钮,选择“完成”,并将其与“返回”按钮连接,如下所示。
输出
当我们在iPhone设备上运行应用程序时,我们将获得以下输出 -
当我们选择“显示模态”时,我们将获得以下输出 -
iOS - 自动布局
自动布局在iOS 6.0中引入。当我们使用自动布局时,我们的部署目标应为 6.0 或更高。自动布局帮助我们创建可用于多种方向和多种设备的界面。
我们示例的目标
我们将添加两个按钮,它们将放置在距屏幕中心一定距离的位置。我们还将尝试添加一个可调整大小的文本字段,该字段将放置在按钮上方的某个距离。
我们的方法
我们将在代码中添加一个文本字段和两个按钮以及它们的约束。每个 UI 元素的约束将被创建并添加到父视图。我们必须禁用我们添加的每个 UI 元素的自动调整大小才能获得所需的结果。
涉及的步骤
**步骤 1** - 创建一个简单的基于视图的应用程序。
步骤 2 - 我们将只编辑 ViewController.m,如下所示 -
#import "ViewController.h" @interface ViewController () @property (nonatomic, strong) UIButton *leftButton; @property (nonatomic, strong) UIButton *rightButton; @property (nonatomic, strong) UITextField *textfield; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIView *superview = self.view; /*1. Create leftButton and add to our view*/ self.leftButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.leftButton.translatesAutoresizingMaskIntoConstraints = NO; [self.leftButton setTitle:@"LeftButton" forState:UIControlStateNormal]; [self.view addSubview:self.leftButton]; /* 2. Constraint to position LeftButton's X*/ NSLayoutConstraint *leftButtonXConstraint = [NSLayoutConstraint constraintWithItem:self.leftButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:superview attribute: NSLayoutAttributeCenterX multiplier:1.0 constant:-60.0f]; /* 3. Constraint to position LeftButton's Y*/ NSLayoutConstraint *leftButtonYConstraint = [NSLayoutConstraint constraintWithItem:self.leftButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:superview attribute: NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]; /* 4. Add the constraints to button's superview*/ [superview addConstraints:@[ leftButtonXConstraint, leftButtonYConstraint]]; /*5. Create rightButton and add to our view*/ self.rightButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.rightButton.translatesAutoresizingMaskIntoConstraints = NO; [self.rightButton setTitle:@"RightButton" forState:UIControlStateNormal]; [self.view addSubview:self.rightButton]; /*6. Constraint to position RightButton's X*/ NSLayoutConstraint *rightButtonXConstraint = [NSLayoutConstraint constraintWithItem:self.rightButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:superview attribute: NSLayoutAttributeCenterX multiplier:1.0 constant:60.0f]; /*7. Constraint to position RightButton's Y*/ rightButtonXConstraint.priority = UILayoutPriorityDefaultHigh; NSLayoutConstraint *centerYMyConstraint = [NSLayoutConstraint constraintWithItem:self.rightButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:superview attribute: NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]; [superview addConstraints:@[centerYMyConstraint, rightButtonXConstraint]]; //8. Add Text field self.textfield = [[UITextField alloc]initWithFrame: CGRectMake(0, 100, 100, 30)]; self.textfield.borderStyle = UITextBorderStyleRoundedRect; self.textfield.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:self.textfield]; //9. Text field Constraints NSLayoutConstraint *textFieldTopConstraint = [NSLayoutConstraint constraintWithItem:self.textfield attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:60.0f]; NSLayoutConstraint *textFieldBottomConstraint = [NSLayoutConstraint constraintWithItem:self.textfield attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self.rightButton attribute:NSLayoutAttributeTop multiplier:0.8 constant:-60.0f]; NSLayoutConstraint *textFieldLeftConstraint = [NSLayoutConstraint constraintWithItem:self.textfield attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute: NSLayoutAttributeLeft multiplier:1.0 constant:30.0f]; NSLayoutConstraint *textFieldRightConstraint = [NSLayoutConstraint constraintWithItem:self.textfield attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute: NSLayoutAttributeRight multiplier:1.0 constant:-30.0f]; [superview addConstraints:@[textFieldBottomConstraint , textFieldLeftConstraint, textFieldRightConstraint, textFieldTopConstraint]]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
注意事项
在标记为 1、5 和 8 的步骤中,我们分别以编程方式添加了两个按钮和一个文本字段。
在其余步骤中,我们创建了约束并将这些约束添加到相应的父视图,这些父视图实际上是 self-views。左侧按钮之一的约束如下所示 -
NSLayoutConstraint *leftButtonXConstraint = [NSLayoutConstraint constraintWithItem:self.leftButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:superview attribute: NSLayoutAttributeCenterX multiplier:1.0 constant:-60.0f];
我们有 constraintWithItem 和 toItem,它们决定我们在哪些 UI 元素之间创建约束。属性决定这两个元素如何关联在一起。“relatedBy”决定属性在元素之间产生多少影响。乘数是乘法因子,常数将添加到乘数中。
在上面的示例中,leftButton 的 X 始终大于或等于相对于父视图中心的 -60 像素。类似地,定义了其他约束。
输出
当我们运行应用程序时,我们将在 iPhone 模拟器上获得以下输出 -
当我们将模拟器的方向更改为横向时,我们将获得以下输出 -
当我们在 iPhone 5 模拟器上运行相同的应用程序时,我们将获得以下输出 -
当我们将模拟器的方向更改为横向时,我们将获得以下输出 -
iOS - Twitter 和 Facebook
Twitter 已集成到iOS 5.0中,Facebook 已集成到iOS 6.0中。我们的教程重点介绍 Apple 提供的类,Twitter 和 Facebook 的部署目标分别为 iOS 5.0 和 iOS 6.0。
涉及的步骤
**步骤 1** - 创建一个简单的基于视图的应用程序。
步骤 2 - 选择您的项目文件,然后选择目标,然后在选择框架中添加Social.framework和Accounts.framework。
步骤 3 - 添加两个名为 facebookPost 和 twitterPost 的按钮,并为它们创建 ibActions。
**步骤 4** - 如下更新**ViewController.h** -
#import <Social/Social.h> #import <Accounts/Accounts.h> #import <UIKit/UIKit.h> @interface ViewController : UIViewController -(IBAction)twitterPost:(id)sender; -(IBAction)facebookPost:(id)sender; @end
**步骤 5** - 如下更新**ViewController.m** -
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(IBAction)facebookPost:(id)sender { SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook]; SLComposeViewControllerCompletionHandler myBlock = ^(SLComposeViewControllerResult result){ if (result == SLComposeViewControllerResultCancelled) { NSLog(@"Cancelled"); } else { NSLog(@"Done"); } [controller dismissViewControllerAnimated:YES completion:nil]; }; controller.completionHandler = myBlock; //Adding the Text to the facebook post value from iOS [controller setInitialText:@"My test post"]; //Adding the URL to the facebook post value from iOS [controller addURL:[NSURL URLWithString:@"http://www.test.com"]]; //Adding the Text to the facebook post value from iOS [self presentViewController:controller animated:YES completion:nil]; } -(IBAction)twitterPost:(id)sender { SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; [tweetSheet setInitialText:@"My test tweet"]; [self presentModalViewController:tweetSheet animated:YES]; } @end
输出
当我们运行应用程序并点击 facebookPost 时,我们将获得以下输出 -
当我们点击 twitterPost 时,我们将获得以下输出 -
iOS - 内存管理
iOS 中的内存管理最初是非 ARC(自动引用计数),我们必须保留和释放对象。现在,它支持 ARC,我们不必保留和释放对象。Xcode 会在编译时自动处理这项工作。
内存管理问题
根据 Apple 文档,内存管理中的两个主要问题是 -
释放或覆盖仍在使用的數據。这会导致内存损坏,通常会导致您的应用程序崩溃,或者更糟糕的是,用户数据损坏。
不释放不再使用的數據会导致内存泄漏。当分配的内存未被释放,即使它永远不会再次使用,这被称为内存泄漏。泄漏会导致您的应用程序使用越来越多的内存,这反过来可能会导致系统性能下降或(在 iOS 中)您的应用程序被终止。
内存管理规则
我们拥有我们创建的对象,并且必须在不再需要它们时随后释放它们。
使用 Retain 获取您未创建的对象的所有权。您也必须在不需要这些对象时释放它们。
不要释放您不拥有的对象。
在 ARC 中处理内存
您不需要在 ARC 中使用 release 和 retain。因此,所有视图控制器的对象都将在视图控制器被移除时释放。同样,任何对象的子对象都将在它们被释放时被释放。请注意,如果其他类对某个类的对象具有强引用,则整个类将不会被释放。因此,建议对委托使用弱属性。
内存管理工具
我们可以借助 Xcode 工具 Instruments 分析内存的使用情况。它包括 Activity Monitor、Allocations、Leaks、Zombies 等工具。
分析内存分配的步骤
步骤 1 - 打开一个现有的应用程序。
步骤 2 - 选择 Product,然后选择 Profile,如下所示。
步骤 3 - 在下一个屏幕中选择 Allocations,然后选择 Profile。
步骤 4 - 我们将看到不同对象的内存分配,如下所示。
步骤 5 - 您可以在视图控制器之间切换,并检查内存是否已正确释放。
步骤 6 - 同样,我们可以使用 Activity Monitor 来查看为应用程序分配的总内存,而不是 Allocations。
步骤 7 - 这些工具帮助我们访问我们的内存消耗并找到可能发生泄漏的位置。
iOS - 应用程序调试
在开发应用程序时,我们可能会犯错误,这会导致各种错误。为了修复这些错误或 bug,我们需要调试应用程序。
选择调试器
Xcode 有两个调试器,即 GDB 和 LLDB 调试器。默认情况下选择 GDB。LLDB 是 LLVM 开源编译器项目的一部分的调试器。您可以通过“编辑活动方案”选项更改调试器。
如何查找编码错误?
要查找与编码相关的错误,您需要构建您的应用程序,它将编译代码。如果代码包含错误,编译器将显示所有消息、错误和警告以及它们可能的原因。
您可以点击 Product,然后点击 Analyze 以查找应用程序中可能存在的问题。
设置断点
断点帮助我们了解应用程序对象的不同状态,这有助于我们识别许多缺陷,包括逻辑问题。我们只需要点击行号即可创建断点。要删除断点,只需单击并将其拖出即可。以下屏幕截图显示了如何设置断点 -
当我们运行应用程序并选择 playVideo 按钮时,应用程序将在我们设置断点的那一行暂停。它使我们有时间分析应用程序的状态。当断点被触发时,我们将获得如下所示的输出。
您可以轻松识别哪个线程触发了断点。在底部,您可以看到 self、sender 等对象,它们保存相应对象的值,我们可以扩展其中一些对象,并查看每个对象的状态。
要继续应用程序,我们将选择继续按钮(最左边的按钮),如下图所示的调试区域中。其他选项包括单步进入、单步跳出和单步执行。
异常断点
我们还有异常断点,它会在发生异常的位置触发应用程序停止。我们可以通过选择调试导航器后选择“+”按钮来插入异常断点。您将看到以下窗口。
然后我们需要选择“添加异常断点”,这将显示以下窗口。
您可以在Xcode 4 用户指南中收集有关调试和其他 Xcode 功能的更多信息。