RedRain的简书:http://www.jianshu.com/users/29e03e6ff407/latest_articles
30个Projects法术一 : GoodAsOldPhones
Swift的语法中 Mark 和 OC 稍有变化
- Swift
// MARK: - tableView set
- Objective-C
#pragma mark -
法术二 : LoveTweet
Swift类型中的方法名称 和 NS库中的也是有区别的, 好在可以方便的做出转换.
Calendar
转为 NSCalendar
类型
// 获取年龄
let gregorian = Calendar(identifier: Calendar.Identifier.gregorian)
let now = Date()
let components = (gregorian as NSCalendar?)?.components(NSCalendar.Unit.year, from: birthdayPicker.date, to: now, options: [])
let age:Int! = components?.year
法术三 : Stopwatch
知识点1: fileprivate 与 private 的辨析
在原有的swift中的 private其实并不是真正的私有,如果一个变量定义为private,在同一个文件中的其他类依然是可以访问到的。这个场景在使用extension的时候很明显。
class User {
private var name = "private"
}
extension User{
var accessPrivate: String {
return name
}
}
这样带来了两个问题:
- 当我们标记为private时,意为真的私有还是文件内可共享呢?
- 当我们如果意图为真正的私有时,必须保证这个类或者结构体在一个单独的文件里。否则可能同文件里其他的代码访问到。
由此,在swift 3中,新增加了一个 fileprivate来显式的表明,这个元素的访问权限为文件内私有。过去的private对应现在的fileprivate。现在的private则是真正的私有,离开了这个类或者结构体的作用域外面就无法访问。
知识点2:Select类型的小写法
给一个Action设置Selector, 可以使用关键字#selector(ClassName.methodName)
Timer.scheduledTimer(timeInterval: 0.1,
target: self,
selector: #selector(ViewController.updateMainTimer),
userInfo: nil,
repeats: true)
也可以提前用常量定义好, 在进一步的话, 可以给Selector添加属性:
fileprivate extension Selector {
static let updateMainTimer = #selector(ViewController.updateMainTimer)
static let updateLapTimer = #selector(ViewController.updateLapTimer)
}
使用时如下:
Timer.scheduledTimer(timeInterval: 0.035,
target: self,
selector: Selector.updateMainTimer,
userInfo: nil,
repeats: true)
法术四 : Todo
在类的外面创建一个Array对象, 他就是一个全局了数组了, 再结合Swift项目不用import头文件, 就可以直接使用这个全局的对象了.
var todos: [String] = []
法术五 : Artistry
1.卫式编程
Swift提供提供了一个关键字为 guard
, 以读取Bundle为例写一个方法
var artists = [Artist]()
guard let url = Bundle.main.url(forResource: "artists", withExtension: "json") else {
return artists
}
可以看到 url(forResource: withExtension:)方法返回值是一个可选值.
利用guard作为判断, 如果读取失败, 则直接 return. 来实现防御式写法.
2.异常捕获的用法
如果遇到方法带有 throws
, 需要对方法进行捕获.
public init(contentsOf url: URL) throws
方法一: 手动捕获
do{
let data = try Data(contentsOf: url)
}catch{
}
方法二: 利用卫式编程
try?方式(常用方式) 系统帮助我们处理异常,如果该方法出现了异常,则该方法返回nil.如果没有异常,则返回对应的对象
guard let anyObject = try? NSJSONSerialization.JSONObjectWithData(jsonData, options: .MutableContainers) else {
return
}
法术六 : CandySearch
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredCandies = candies.filter { candy in
let categoryMatch = (scope == "All") || (candy.category == scope)
return categoryMatch && candy.name.lowercased().contains(searchText.lowercased())
}
tableView.reloadData()
}
知识点1:
此方法第二个参数填写了默认值, 在调用这个方法的时候, 如果只传递第一个参数.第二个参数会使用默认值.
知识点2:
使用Array中的方法filter, 过滤得到需要的数组内的对象.
法术七 : PokedexGo
RxCocoa 和 RxSwift 函数式编程框架
法术八 : SimpleRSSReader
用元祖封装简单的数据结构, 作为整体进行传递.
声明一个装有元祖的数组:
var rssItems: [(title: String, description: String, pubDate: String)]?
给cell赋值:
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! NewsTableViewCell
if let item = rssItems?[indexPath.row] {
(cell.titleLabel.text, cell.descriptionLabel.text, cell.dateLabel.text) = (item.title, item.description, item.pubDate)
}
法术九 : PhotoScroll
使用if
进行连续解包 , 当遇到为 nil 时不进行后面的解包.
if let cell = sender as? UICollectionViewCell,
let indexPath = collectionView?.indexPath(for: cell),
let zoomedPhotoViewController = segue.destination as? ZoomedPhotoViewController
{
zoomedPhotoViewController.photoName = "photo\(indexPath.row + 1)"
}
法术十 : Interests
代理方法的第三个参数是 指针传递
, 通过修改第三个参数, 可以控制scrollView的最终位置.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthWithSpace = layout.itemSize.width + layout.minimumLineSpacing
var offset = targetContentOffset.pointee
let index = (offset.x + scrollView.contentInset.left) / cellWidthWithSpace
let roundedIndex = round(index)
offset = CGPoint(x: roundedIndex * cellWidthWithSpace - scrollView.contentInset.left, y: -scrollView.contentInset.top)
}
网友评论