ios swift模仿qq登陆界面,xml布局
给大家推荐两个学习的地址:
极客学院的视频:http://www.jikexueyuan.com/path/ios/
一个博客:http://blog.csdn.net/lizhongfu2013/article/details/29210015
主要想要实现一个模仿的登陆界面
代码:
- //
- // LoginViewController.swift
- // IBM_LOGIN
- //
- // Created by dcintern on 6/26/15.
- // Copyright (c) 2015 dcintern. All rights reserved.
- //
- //import Foundation
- import UIKit
- class LoginViewController: UIViewController
- {
- /// 定义属性
- var QQNumber = UITextField()
- var PassNumber = UITextField()
- override func viewDidLoad() {
- self.view.backgroundColor = UIColor.whiteColor()
- super.viewDidLoad()
- // 添加头图片
- [self .addAllSubViews()];
- }
- // 添加所有子控件
- func addAllSubViews(){
- /// 平铺背景
- var headImage = UIImageView(frame: CGRectMake(0,0, 400, 800))
- headImage.image = UIImage(named:"123.jpeg")
- self.view.addSubview(headImage)
- /// QQ号输入提示,暂时没有用到
- var phoneText = UILabel(frame: CGRectMake(30, 240, UIScreen.mainScreen().bounds.size.width-60, 30))
- phoneText.text = ""
- self.view.addSubview(phoneText)
- /// QQ号输入框
- var QQNumber = UITextField(frame: CGRectMake(30, 150, UIScreen.mainScreen().bounds.size.width-60, 30))
- QQNumber.placeholder = " username"
- QQNumber.layer.borderWidth = 2
- QQNumber.layer.borderColor = UIColor.lightGrayColor().CGColor
- QQNumber.layer.cornerRadius = 5
- QQNumber.keyboardType = UIKeyboardType.NumberPad
- self.view.addSubview(QQNumber)
- self.QQNumber = QQNumber
- /// 密码输入提示,暂时没用到
- var passText = UILabel(frame: CGRectMake(30, 300, UIScreen.mainScreen().bounds.size.width-60, 30))
- passText.text = ""
- self.view.addSubview(passText)
- /// 密码输入框
- var PassNumber = UITextField(frame: CGRectMake(30, 200, UIScreen.mainScreen().bounds.size.width-60, 30))
- PassNumber.placeholder = " password"
- PassNumber.layer.borderWidth = 2
- PassNumber.layer.borderColor = UIColor.lightGrayColor().CGColor
- PassNumber.layer.cornerRadius = 5
- self.view.addSubview(PassNumber)
- self.PassNumber = PassNumber
- /// 密码找回
- var button = UIButton(frame: CGRectMake(200, 360, 120, 30))
- UIButton.buttonWithType(UIButtonType.Custom)
- button.setTitle("忘记密码", forState: UIControlState.Normal)
- button.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
- self.view.addSubview(button)
- button.addTarget(self, action: "onClick", forControlEvents: UIControlEvents.TouchUpInside)
- }
- /// 密码找回方法实现
- func onClick()
- {
- ///找回密码提示
- UIAlertView(title: "温馨提示", message: "新密码已发送至手机上", delegate: nil, cancelButtonTitle: "确定", otherButtonTitles: "取消").show()
- }
- /**
- 点击界面键盘辞去第一响应者
- */
- override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
- {
- self.QQNumber.resignFirstResponder()
- self.PassNumber.resignFirstResponder()
- }
- }
实现根据xml进行布局:
- import UIkit
- class LoginViewController : UIViewController,NSXMLParserDelegate
- {
- ///
- /// 定义属性
- var m_Username = UITextField()
- var m_Password = UITextField()
- var m_backgroundRect = CGRectMake(0,0,0,0)
- var m_UsernameRect = CGRectMake(0,0,0,0)
- var m_PassWordRect = CGRectMake(0,0,0,0)
- var m_ConnectRect = CGRectMake(0,0,0,0)
- var m_ForgetRect = CGRectMake(0,0,0,0)
- var myActivityIndicator: UIActivityIndicatorView!
- override func viewDidLoad()
- {
- self.view.backgroundColor = UIColor.whiteColor()
- super.viewDidLoad()
- var parser = NSXMLParser(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("LoginLayout", ofType: "xml")!))
- parser?.delegate = self
- parser?.parse()
- // 添加头图片
- [self .addAllSubViews()];
- }
- // 添加所有子控件
- func addAllSubViews()
- {
- /// 平铺背景
- // var headImage = UIImageView(frame: m_backgroundRect)
- // headImage.image = UIImage(named:"background.jpg")
- //self.view.addSubview(headImage)
- //float lightblue[]={0.6824f, 0.7882f, 1.0f, 1.0f};
- //var color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), myColor)
- ServerAddress.layer.borderColor = UIColor.blackColor().CGColor
- ServerAddress.layer.cornerRadius = 5
- self.view.addSubview(ServerAddress)
- self.m_ServerAddress = ServerAddress
- /// username input textbox
- var Username = UITextField(frame: m_UsernameRect)
- Username.placeholder = " username"
- Username.layer.borderWidth = 2
- Username.layer.borderColor = UIColor.blackColor().CGColor
- Username.layer.cornerRadius = 5
- self.view.addSubview(Username)
- self.m_Username = Username
- /// password input textbox
- var Password = UITextField(frame: m_PassWordRect)
- Password.placeholder = " password"
- Password.layer.borderWidth = 2
- Password.layer.borderColor = UIColor.blackColor().CGColor
- Password.layer.cornerRadius = 5
- self.view.addSubview(Password)
- self.m_Password = Password
- /// confirm the connection button
- var confirmbutton = UIButton(frame: m_ConnectRect)
- UIButton.buttonWithType(UIButtonType.Custom)
- confirmbutton.setTitle("Connect", forState: UIControlState.Normal)
- confirmbutton.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
- self.view.addSubview(confirmbutton)
- confirmbutton.addTarget(self, action: "onClickConfirm", forControlEvents: UIControlEvents.TouchUpInside)
- /// findback password button
- var button = UIButton(frame: m_ForgetRect)
- UIButton.buttonWithType(UIButtonType.Custom)
- button.setTitle("Forget password!", forState: UIControlState.Normal)
- button.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
- self.view.addSubview(button)
- button.addTarget(self, action: "onClickFindPasswordBack", forControlEvents: UIControlEvents.TouchUpInside)
- // myActivityIndicator = UIActivityIndicatorView()
- //myActivityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
- //myActivityIndicator.center = self.view.center;
- myActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .White)
- myActivityIndicator.frame = CGRectMake(self.view.frame.size.width/2 - 50, 250, 100, 100)
- myActivityIndicator.color = UIColor.blackColor()
- self.view.addSubview(myActivityIndicator);
- }
- ///on confirm connettion
- func onClickConfirm()
- {
- ///check if ip,username,passname is correct
- println(m_ServerAddress.text)
- //eares the space before and after
- }
- /// 密码找回方法实现
- func onClickFindPasswordBack()
- {
- ///找回密码提示, otherButtonTitles: "取消"这个参数如何传进去?
- UIAlertView(title: "温馨提示", message: "新密码已发送至手机上", delegate: nil, cancelButtonTitle: "确定").show()
- }
- /**
- 点击界面键盘辞去第一响应者
- */
- override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
- {
- self.m_Username.resignFirstResponder()
- self.m_Password.resignFirstResponder()
- }
- var currentNodeName:String!
- func parser(parser: NSXMLParser, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!)
- {
- currentNodeName = elementName
- //review the code using swith
- if elementName == "background"
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_backgroundRect = CGRectMake(x,y,Width,Height)
- }
- else if(elementName == "ServerAddress")
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_ServerAddressRect = CGRectMake(x,y,Width,Height)
- }
- else if(elementName == "Username")
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_UsernameRect = CGRectMake(x,y,Width,Height)
- }
- else if(elementName == "Password")
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_PassWordRect = CGRectMake(x,y,Width,Height)
- }
- else if(elementName == "Connect")
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_ConnectRect = CGRectMake(x,y,Width,Height)
- }
- else if(elementName == "Forget")
- {
- let x = CGFloat(((attributeDict["x"]! as String )as NSString).floatValue)
- let y = CGFloat(((attributeDict["y"]! as String ) as NSString).floatValue)
- let Width = CGFloat(((attributeDict["Width"]! as String )as NSString).floatValue)
- let Height = CGFloat(((attributeDict["Height"]! as String ) as NSString).floatValue)
- m_ForgetRect = CGRectMake(x,y,Width,Height)
- }
- }
- func parser(parser: NSXMLParser, foundCharacters string: String!) {
- // println(string)
- var str = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
- if str != ""{
- println("current node : \(currentNodeName),value : \(str)")
- }
- }
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
- lazy var m_connect: ConnectServer? = {
- return ConnectServer()
- }()
- }
xml:
- <LoginLayout>
- <background x="0" y="0" Width="400" Height="800">
- <Image name="background.jpg"> </Image>
- </background>
- <Username x="30" y="150" Width="300" Height="30">
- </Username>
- <Password x="30" y="200" Width="300" Height="30">
- </Password>
- <Connect x="30" y="250" Width="100" Height="30">
- </Connect>
- <Forget x="200" y="250" Width="200" Height="30">
- </Forget>
- </LoginLayout>
对xml解析类的封装:
NSXMLParser(data: data),这个有几种初始化的方法,但是string就不行,得转换成NSdata,还是比较蛋疼的
- //
- // VMXMLParser.swift
- // XMLParserTest
- //
- // Created by Jimmy Jose on 22/08/14.
- //https://github.com/varshylmobile/VMXMLParser
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- import Foundation
- // Todo: Add documentation
- class VMXMLParser: NSObject,NSXMLParserDelegate{
- private let kParserError = "Parser Error"
- private var activeElement = ""
- private var previousElement = "-1"
- private var previousElementValue = ""
- private var arrayFinalXML = NSMutableArray()
- private var dictFinalXML = NSMutableDictionary()
- private var completionHandler:((tags:NSArray?, error:String?)->Void)?
- var lameMode = true
- var reoccuringTag:NSString = ""
- var m_Projects:[String] = []
- /**
- Initializes a new parser with url of NSURL type.
- :param: url The url of xml file to be parsed
- :param: completionHandler The completion handler
- :returns: Void.
- */
- override init() {
- super.init()
- }
- func parseXMLFromURL(url:NSURL,takeChildOfTag:NSString,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- self.reoccuringTag = takeChildOfTag
- VMXMLParser().initWithURL(url, completionHandler: completionHandler)
- }
- func parseXMLFromURLString(urlString:NSString,takeChildOfTag:NSString,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- self.reoccuringTag = takeChildOfTag
- initWithURLString(urlString, completionHandler: completionHandler)
- }
- func parseXMLFromData(data:NSData,takeChildOfTag:NSString,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- self.reoccuringTag = takeChildOfTag
- initWithContentsOfData(data, completionHandler:completionHandler)
- }
- class func initParserWithURL(url:NSURL,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- VMXMLParser().initWithURL(url, completionHandler: completionHandler)
- }
- class func initParserWithURLString(urlString:NSString,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- VMXMLParser().initWithURLString(urlString, completionHandler: completionHandler)
- }
- class func initParserWithData(data:NSData,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- VMXMLParser().initWithContentsOfData(data, completionHandler:completionHandler)
- }
- private func initWithURL(url:NSURL,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil) -> AnyObject {
- parseXMLForUrl(url :url, completionHandler: completionHandler)
- return self
- }
- private func initWithURLString(urlString :NSString,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil) -> AnyObject {
- let url = NSURL(string: urlString as String)!
- parseXMLForUrl(url :url, completionHandler: completionHandler)
- return self
- }
- private func initWithContentsOfData(data:NSData,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil) -> AnyObject {
- initParserWith(data: data)
- return self
- }
- private func parseXMLForUrl(#url:NSURL,completionHandler:((tags:NSArray?, error:String?)->Void)? = nil){
- self.completionHandler = completionHandler
- beginParsingXMLForUrl(url)
- }
- private func beginParsingXMLForUrl(url:NSURL){
- let request:NSURLRequest = NSURLRequest(URL:url)
- let queue:NSOperationQueue = NSOperationQueue()
- NSURLConnection.sendAsynchronousRequest(request,queue:queue,completionHandler:{response,data,error in
- if(error != nil){
- if(self.completionHandler != nil){
- self.completionHandler?(tags:nil,error:error.localizedDescription)
- }
- }else{
- self.initParserWith(data: data)
- }})
- }
- private func initParserWith(#data:NSData){
- var parser = NSXMLParser(data: data)
- parser.delegate = self
- var success:Bool = parser.parse()
- if success {
- if(self.arrayFinalXML.count > 0)
- {
- if(self.completionHandler != nil)
- {
- self.completionHandler?(tags:self.arrayFinalXML,error:nil)
- }
- }
- }
- else
- {
- if(self.completionHandler != nil)
- {
- self.completionHandler?(tags:nil,error:kParserError)
- }
- }
- }
- internal func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {
- activeElement = elementName;
- println(elementName)
- if elementName == "Project"
- {
- let name = (attributeDict["Name"]! as String )
- println(name)
- m_Projects.append(name)
- }
- if(reoccuringTag.isEqualToString(elementName)){
- dictFinalXML = NSMutableDictionary()
- }
- }
- internal func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
- if(reoccuringTag.length == 0){
- if((dictFinalXML.objectForKey(activeElement)) != nil){
- arrayFinalXML.addObject(dictFinalXML)
- dictFinalXML = NSMutableDictionary()
- }else{
- dictFinalXML.setValue(previousElementValue, forKey: activeElement)
- }
- }else{
- //println(elementName)
- if(reoccuringTag.isEqualToString(elementName)){
- arrayFinalXML.addObject(dictFinalXML)
- dictFinalXML = NSMutableDictionary()
- }else{
- dictFinalXML.setValue(previousElementValue, forKey: activeElement)
- }
- }
- previousElement = "-1"
- previousElementValue = ""
- }
- internal func parser(parser: NSXMLParser, foundCharacters string: String?) {
- if var str = string as NSString? {
- str = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
- if((previousElement as NSString).isEqualToString("-1")){
- previousElement = activeElement
- previousElementValue = str as String
- }else{
- if((previousElement as NSString).isEqualToString(activeElement)){
- previousElementValue = previousElementValue + (str as String)
- }else{
- previousElement = activeElement
- previousElementValue = str as String
- }
- }
- }
- }
- internal func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
- if(self.completionHandler != nil){
- self.completionHandler?(tags:nil,error:parseError.localizedDescription)
- }
- }
- }
ios swift模仿qq登陆界面,xml布局的更多相关文章
- Qt 之 模仿 QQ登陆界面——样式篇
一.简述 今天晚上花了半天时间从QQ登录界面抠了些图,顺便加了点样式基本上实现了QQ的登陆界面全部效果.虽不说100%相似,那也有99.99%相似了哈O(∩_∩)O. QQ好像从去年开始,登录界面有了 ...
- [转]Android:布局实例之模仿QQ登录界面
Android:布局实例之模仿QQ登录界面 预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布 ...
- Android:布局实例之模仿QQ登录界面
预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布为 4.分析样式选择器 下拉箭头2种样式:点 ...
- [iOS基础控件 - 3.1] QQ登陆界面
A.storyboard 控件版 1.label 2.textfield a.Keyboard Type 账号:Number Pad 密码:Num ...
- WPF和Expression Blend开发实例:模拟QQ登陆界面打开和关闭特效
不管在消费者的心中腾讯是一个怎么样的模仿者抄袭者的形象,但是腾讯在软件交互上的设计一直是一流的.正如某位已故的知名产品经理所说的:设计并非外观怎样,感觉如何.设计的是产品的工作原理.我觉得腾讯掌握了其 ...
- QQ聊天界面的布局和设计(IOS篇)-第二季
QQChat Layout - 第二季 本来第二季是快写好了, 也花了点功夫, 结果gitbook出了点问题, 给没掉了.有些细节可能会一带而过, 如有疑问, 相互交流进步~. 在第一季中我们完成了Q ...
- QQ聊天界面的布局和设计(IOS篇)-第一季
我写的源文件整个工程会再第二季中发上来~,存在百度网盘, 感兴趣的童鞋, 可以关注我的博客更新,到时自己去下载~.喵~~~ QQChat Layout - 第一季 一.准备工作 1.将假数据messa ...
- java代码完全手写模仿qq登录界面
这是我模仿QQ2015版界面,实现的基本功能有登陆验证,重置等,当然直接复制代码运行是不一样的,还要注意自己插入自己的图片. 结果截图如下所示: import java.awt.BorderLayou ...
- 浅谈HTML之模仿人人网登陆界面(新手必学)
为方便大家对web相关知识的了解,现谈谈新手如何从HTML css Javascript到以后后台的发展.首先,让大家看看HTML仿人人登陆界面: <!doctype html> < ...
随机推荐
- 解决Popup StayOpen=true时,永远置顶的问题
Popup设置了StayOpen=true时,会置顶显示. 如弹出了Popup后,打开QQ窗口,Popup显示在QQ聊天界面之上. 怎么解决问题? 获取绑定UserControl所在的窗口,窗口层级变 ...
- Go 语言多维数组
Go 语言支持多维数组,以下为常用的多维数组声明方式: var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type 以下实例声明了三维的整型数组: ...
- render函数data参数中的model选项
官方文档没有说, 但是编译v-model时, 是有model这个选项的, 例如: _c('el-input', { attrs: { "placeholder": "手机 ...
- UE4使用UMG接口操作界面
原文链接:http://gad.qq.com/article/detail/7181131 本文首发腾讯GAD开发者平台,未经允许,不得转载 UE4的蓝图之强大让人欲罢不能,但是实际在项目的开发中,C ...
- 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置
在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...
- Objective-C点语法
Objective-C点语法 点语法可以简单的理解成是为了让Java等语言的开发人员能够快速适应OC语言而添加的一个新写法 因为Java里没有指针,也没有[xxx xxx]这种调用方式,都是使用点xx ...
- TeamView 无法捕捉画面问题的解决办法
teamview是个非常不错的远程协助软件,你要是在项目中还搞个QQ远程协助啥的就显的非常不专业了. 在teamview连接远程后,看到的是一片漆黑,中间框提示"现在无法捕捉画面.这可能是由 ...
- “出错了”和报告Bug的艺术
"出错了." 没有那句话能像"出错了"一样让程序员/开发者如此沮丧,心里翻江倒海,怒火一点即燃,还要死掉一大片脑细胞. 这句生硬的开场白通常标志着让开发者恐惧的 ...
- Android开发艺术探索——第二章:IPC机制(上)
Android开发艺术探索--第二章:IPC机制(上) 本章主要讲解Android的IPC机制,首先介绍Android中的多进程概念以及多进程开发模式中常见的注意事项,接着介绍Android中的序列化 ...
- React Native之ViewPagerAndroid 组件
概述 今天我们来讲解一下关于 ViewPager 的使用,它是一个允许子视图左右滚动翻页的容器.我们知道在Android开发中系统有ViewPager这个组件,作用是实现滚动翻页的,在RN中也是有这么 ...