初识 swift 封装轮播图
一、简介
换了一家公司、换了一个环境刚开始来公司自然不能有一丝一毫的放松,每天即使是没有什么工作也是看看这个博客、那个源码。尽量让自己更充实。慢慢的开始写几篇博客记录下自己遇到的一些问题和解决方法。其实也没什么就是瞎写没有什么思路反正就是遇到问题然后解决掉、最后分享出去。
随着工作走向正规公司的项目不是那么赶、也就有时间尝试一些新的东西。只是不想刚开始编程哪会那么激进今天学这个明天学那个了。APPLE 发布 swift 有一年多了、不能说好也不能说不好、总之没有了解过时没有话语权的。所以就想试试。一开始我也想过仅使用swift 、后来发现这样做在我目前的项目中是不实际的因为有些东西已经用oc封装的很好了、总不能再花大把大把的时间重新来一次吧!最后决定使用oc+swift 混合编程。
在做 app 开发过程中发现轮播图出现的概率是相当大的。 就先从这个入手吧!
代码没有多的注释、但是简单易读。
二、用到的知识点
构造函数、变量、属性封装、方法重载、
构造函数:如果没有什么特殊的要求我们只要重写父类的构造函数就ok了、如果有特殊的业务需要自定义。
1 2 3 | 1 ) func init ( firstName : String , lastName : String ) 2 ) init ( firstName : String , lastName : String ) 以上两种方式 1 )会报错 2 )正确 |
变量、属性封装:这个一开始特别不适应、主要是 ? ! 这两个符号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 如是代码: 1 )变量 private var _firstName : String = String (); //定义变量并初始化 private var _lastName : String ? //定义变量默认初始化 private var _sex : Bool = true ; private var _age : Int ?; 2 ) 属性 var firstName : String { get { return _firstName } set { _firstName = newValue } // 默认setter 的传人参数名称是 newVlaue } var lastName : String { get { return _lastName } set ( newLastName ){ _lastName = newLastName } // 可以定义setter 传入参数的名称 例如:newLastName } |
对于默认初始化 ‘?’ 的使用大家可以到网上搜索一下、这里讲一下如何使用定义成 ? 的变量或属性的使用。个人总结为:取值使用! 当访问其属性时用?
1 2 3 4 5 6 7 8 9 10 11 12 13 | 例如: private _address : String ?; var Address : String ?{ get { return _address !} // 这里使用 ! set { _address = newValue } } func test (){ self . Address ? debugDescription // 访问该变量的相应属性使用? var emtpy : String ? = self . Address ! // 取值调用! self . Address = empty ! //取值调用 ! } |
? !的使用是相对的。
方法重载:直接看代码
1 2 3 4 5 | func loadData ( image : Array < String > ){ self . loadData ( image , title : nil ); } func loadData ( image : Array < String > , title : Array < String > ?){ } |
二、功能实现
功能实现直接上代码 请导入 SDWebImage 第三方库

protocol KYScrollPageDelegate{ func imageSelectTap(index:Int) } class KYScrollPage: UIView,UIScrollViewDelegate { private var noteTitle:UILabel? private var arrayTitle:Array<String>? private var arrayImage:Array<String>? private var mainScroll:UIScrollView? private var pageControl:UIPageControl? private var currentPage:Int=0; private var pageSize:Int=0; private var titleHeight:CGFloat=20.0; //MARK: ======================================================== 变量 private var _startTimer:Bool = false; private var _timeInterval:Double=2.0; private var _hiddenTitle:Bool=false; private var _colorTitle:UIColor=UIColor.whiteColor(); private var _hiddenPageControl:Bool=false; private var _contentHorizontalAlignment:UIControlContentHorizontalAlignment=UIControlContentHorizontalAlignment.Center var deleagte:KYScrollPageDelegate? override init(frame: CGRect) { super.init(frame: frame); self.mainScroll = UIScrollView(); self.pageControl = UIPageControl(); self.hiddenTitle = false; self.hiddenPageControl = false; self.contentHorizontalAlignment=UIControlContentHorizontalAlignment.Center; } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } //MARK: ======================================================== KYScrollPage 协议实现 func loadData(image:Array<String>){ self.loadData(image, title: nil); } func loadData(image:Array<String> ,title:Array<String>?){ self.arrayImage = image; self.arrayTitle = title!; var tempArray:Array<String>=image; tempArray.insert(image.last!, atIndex: 0); tempArray.append(image.first!); self.arrayImage = tempArray; self.pageSize = self.arrayImage!.count; self.mainScroll!.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); var width:CGFloat = self.frame.size.width * CGFloat(self.pageSize); self.mainScroll?.contentSize=CGSizeMake(width, self.frame.size.height); self.mainScroll?.showsHorizontalScrollIndicator = false; self.mainScroll?.showsVerticalScrollIndicator = false; self.mainScroll?.scrollsToTop = false; self.mainScroll?.pagingEnabled = true; self.mainScroll?.delegate = self; for (var i:Int=0; i<self.pageSize; i++) { let imageUrl:String = self.arrayImage![i]; var imgeView:UIImageView = UIImageView(); if imageUrl.hasPrefix("http://") { imgeView.sd_setImageWithURL(NSURL(string: imageUrl), placeholderImage: UIImage(named:"Icon-60")); } else { imgeView.image=UIImage(named:"Icon-60"); } imgeView.frame = CGRectMake(self.frame.size.width*CGFloat(i), CGFloat(0), self.frame.size.width, self.frame.size.height); imgeView.tag = i; var Tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageGestureTap:")); Tap.numberOfTapsRequired=1; Tap.numberOfTouchesRequired=1; imgeView.userInteractionEnabled=true; imgeView.addGestureRecognizer(Tap); self.mainScroll?.addSubview(imgeView); } self.mainScroll?.setContentOffset(CGPointMake(self.frame.size.width, 0), animated: false); self.addSubview(self.mainScroll!); self.contentHorizontalAlignment = _contentHorizontalAlignment; self.pageControl!.currentPage=0; self.pageControl!.pageIndicatorTintColor = UIColor(red: 155/255.0, green: 155/255.0, blue: 155/255.0, alpha: 1.0); self.pageControl!.currentPageIndicatorTintColor=UIColor.whiteColor(); self.pageControl!.userInteractionEnabled = false; self.pageControl!.numberOfPages=self.pageSize-2; self.pageControl?.hidden=self.hiddenPageControl; self.addSubview(self.pageControl!); if arrayTitle != nil{ self.noteTitle = UILabel(frame:CGRectMake(10,self.frame.size.height-self.titleHeight, self.frame.size.width, self.titleHeight)); self.noteTitle!.text=self.arrayTitle!.first; noteTitle?.textColor = _colorTitle; noteTitle?.backgroundColor=UIColor.clearColor(); noteTitle?.font=UIFont.systemFontOfSize(13.0); noteTitle?.hidden=self.hiddenTitle; self.addSubview(noteTitle!); } } //MARK: - ========================================================= UIScrollView 协议实现 func scrollViewDidScroll(scrollView: UIScrollView) { var pageWidth:CGFloat = scrollView.frame.size.width; var x:CGFloat = scrollView.contentOffset.x; var page:Int = Int(((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1); self.currentPage=page; pageControl!.currentPage=page-1; var titleIndex:Int=page-1; if (titleIndex==self.arrayTitle!.count) { titleIndex=0; } if (titleIndex<0) { titleIndex=self.arrayTitle!.count-1; } if (titleIndex>self.arrayTitle!.count-1) { noteTitle?.text=""; } else { noteTitle?.text=self.arrayTitle![titleIndex]; } } func scrollViewDidEndDecelerating(scrollView: UIScrollView) { if (currentPage==0) { scrollView.setContentOffset(CGPointMake(CGFloat(arrayImage!.count-2)*self.frame.size.width, CGFloat(0)), animated: false) } if (currentPage==(self.arrayImage!.count-1)) { scrollView.setContentOffset(CGPointMake(self.frame.size.width, CGFloat(0)), animated: false) } } @objc private func imageGestureTap(getsture:UITapGestureRecognizer){ if (self.deleagte != nil) { self.deleagte?.imageSelectTap(getsture.view!.tag); } } // pagecontrol 选择器的方法 func turnPage() { var page:Int = self.pageControl!.currentPage; self.mainScroll?.scrollRectToVisible(CGRectMake(CGFloat(self.frame.size.width*CGFloat(page+1)),0,self.frame.size.width,self.frame.size.height), animated: false); } // 定时器 绑定的方法 func runTimePage() { var page:Int = self.pageControl!.currentPage; // 获取当前的page page++; page = page >= self.arrayImage!.count-2 ? 0 : page ; self.pageControl!.currentPage = page; self.turnPage(); } //MARK: ======================================================== 属性封装 /// 图片标题是否显示 var hiddenTitle:Bool { get{ return _hiddenTitle;} set{ _hiddenTitle = newValue; if noteTitle != nil { self.noteTitle?.hidden=_hiddenTitle; } } } /// 图片标题颜色 var colorTitle:UIColor{ get{ return _colorTitle} set{ _colorTitle = newValue; if noteTitle != nil { self.noteTitle?.textColor=_colorTitle; } } } /// 是否显示 UIPageControl var hiddenPageControl:Bool{ get{return _hiddenPageControl} set{ _hiddenPageControl = newValue; if pageControl != nil { self.pageControl?.hidden=_hiddenPageControl; } } } /// UIPagerControl 显示位置 var contentHorizontalAlignment:UIControlContentHorizontalAlignment{ get{ return _contentHorizontalAlignment } set{ _contentHorizontalAlignment = newValue; let size:CGSize = self.pageControl!.sizeForNumberOfPages(pageSize) switch _contentHorizontalAlignment { case UIControlContentHorizontalAlignment.Center : self.pageControl?.center=CGPointMake(self.center.x, self.frame.size.height-self.titleHeight+self.titleHeight/2) break; case UIControlContentHorizontalAlignment.Left : self.pageControl?.frame.origin.x=size.width/2; break; case UIControlContentHorizontalAlignment.Right : self.pageControl?.frame.origin.x=self.frame.size.width-size.width/2 break; default: break; } } } /// 计时器 var startTimer:Bool{ get{ return _startTimer} set{ _startTimer = newValue; if _startTimer { NSTimer.scheduledTimerWithTimeInterval(_timeInterval, target: self, selector: Selector("runTimePage"), userInfo: nil, repeats: true); } } } }
调用代码:
1 2 3 4 5 6 7 8 9 10 | var headerView : KYScrollPage ? = KYScrollPage ( frame : CGRectMake ( 0 , 0 , self . view . frame . size . width , 150 )); headerView ?. contentHorizontalAlignment = UIControlContentHorizontalAlignment . Right ; headerView ?. hiddenTitle = false ; headerView ?. startTimer = true ; headerView !. loadData ([ "http://img0.bdstatic.com/img/image/b4ff47b072b4b8934864f4be92ee07c01409737708.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" , "http://f.hiphotos.baidu.com/image/w%3D230/sign=17e661b9eb50352ab161220b6343fb1a/8435e5dde71190ef5bd3fcd1cc1b9d16fdfa6097.jpg" ], title : [ "成龙1" , "成龙2" , "成龙2" , "成龙2" , "成龙2" , "成龙2" , "成龙2" ]); headerView ?. deleagte = self ; self . tableView . tableHeaderView = headerView ; |
三、问题总结
开始做的时候确实遇到了几个问题
1、 属性封装的问题
由于oc 用习惯了总以为 每个属性都有一个默认的字段 _属性 所以在 get{return ...} 花费了些时间
set{_属性=....} 不晓得默认的字段名称花费了些时间
swift 的属性应该是和java 很像。对应定义一个私有成员变量。
2、类型不匹配的问题
由于不明白 ? ! 怎么使用 总是会遇到类型转换不匹配
等号右边的报错通常需要对不一致的类型进行强转 、对于?标示的要 使用 ! 取值。
3、初始值的问题
变量、属性 声明后没有赋值或者标示为 ? 在构造函数总是报错。swift 变量、属性必须初始化。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?