一些开发中不常用但很实用的小技能,可能就一行代码,随时更新,个人备忘
最近经常纠结在各种不常用的小问题上。比如cell上因为文字内容不固定而不固定cell的行高,除了在tableView: heightForRowAtIndexPath: 这个协议方法中动态加载之外,有一个一行代码就可以解决的方法。不过目前只是想到这个问题,并没有想起是哪一行代码,什么时候想起来什么时候来填坑吧。随时更新各种小技巧。
1. 设置UITableView上cell上的线条Style
tmpTableView?.separatorStyle = UITableViewCellSeparatorStyle.None
这样UITableView的cell上的横线就没了,不会再有滚动tableView时忽隐忽现的线条的出现了。其余还有
public enum UITableViewCellSeparatorStyle : Int {
case None
case SingleLine // 显而易见:单行横线
case SingleLineEtched // This separator style is only supported for grouped style table views currently 目前这种分割线样式只能在UITableView的style是Grouped时使用
}
2.获取应用的Bundle Identifier
NSString *identifier = [[NSBundle mainBundle] bundleIdentifier];
就上面的一段代码。
针对NSBundle有三个函数需要注意,这些函数都是针对info.plist操作的,可以获取对应的键值:
bundleIdentifier,返回NSString类型的bundle identifier
infoDictionary,返回整个info.plist内容,返回类型NSDictionary
objectForInfoDictionaryKey:,依据Key值返回对应的键值
不过需要指出的是上述dictionary的key值并不是显示在plist中的字符串,这一点通过打印出infoDictionary的结果就可以看出。
NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString")! 用来获取版本号。
3.视图控制器上嵌套视图控制器
self.addChildViewController(self.pageMenu!)
self.view.addSubview(self.pageMenu!.view)
self.pageMenu!.didMoveToParentViewController(self)
4.设置导航栏颜色
self.navigationController.navigationBar.barTintColor = UIColor.blueColor()
其中,在iOS7.0之前可以设置TintColor,能达成一样的效果。
5.关于导航栏半透明与否导致的控件下压
// 取消透明半模糊状态
self.navigationController?.navigationBar.translucent = false;
默认是true,也就是半透明的,半透明的时候我们计算控件frame的y值时需要从整个屏幕的最上方计算。而若设置为false,则计算frame从导航栏的下底边开始计算。
6.电源条(状态栏)的默认颜色
// 设置电源条背景为白色
UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true)
依然是枚举
public enum UIStatusBarStyle : Int {
case Default // Dark content, for use on light backgrounds 黑色的内容(默认样式),用在亮的背景下
@available(iOS 7.0, *)
case LightContent // Light content, for use on dark backgrounds 白色的内容,用在黑色的背景下
}
所谓的内容,就是包括 运营商信息、时间和电源电量等其他的内容。
另外,在使用这个方法时,官方有备注:
// Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
也就是说,你需要去info.plist中添加新的字段UIViewController-based status bar system,将其值改为NO,设置电源条状态才会生效。
7.NSCalendar日历
NSCalendar是一个日历类。它的主要作用是能通过本机的时间或者网络的时间来给我们提供年月日时分秒的确切时间。怎么使用它呢?
7.1获取本机时间
1 // 获取日历对象 2 let cal = NSCalendar.currentCalendar()
通过它我们可以获取本地的日历,也就是你电源条上的日历。
7.2通过网络获取日历
1 @available(iOS 2.0, *) 2 public class func autoupdatingCurrentCalendar() -> NSCalendar // tracks changes to user's preferred calendar identifier 3 4 /* 5 This method returns a new autoreleased calendar object of the given type, specified by a calendar identifier constant. 6 The calendar defaults to having the current locale and default time zone, for those properties. 7 */ 8 @available(iOS 8.0, *) 9 public /*not inherited*/ init?(identifier calendarIdentifierConstant: String) 10 11 public init?(calendarIdentifier ident: String)
通过网络或者标识符获取日历。不再赘述。
获得了日历,我们怎么获取时间呢?
首先,我们需要当前的时间:
1 var date = cal.startOfDayForDate(NSDate())
然后通过这个时间,我们就能获得精确的时间了:
1 let year = cal.component(NSCalendarUnit.Year, fromDate: date)
其余的 月/日/时/分/秒 等等也可以通过类似的方式获得。我们只需要修改结构体 NSCalendarUnit的不同变量就可以了:
1 public struct NSCalendarUnit : OptionSetType { 2 public init(rawValue: UInt) 3 // 可以看出,这些变量都是get-only只读的 4 public static var Era: NSCalendarUnit { get } 5 public static var Year: NSCalendarUnit { get } 6 public static var Month: NSCalendarUnit { get } 7 public static var Day: NSCalendarUnit { get } 8 public static var Hour: NSCalendarUnit { get } 9 public static var Minute: NSCalendarUnit { get } 10 public static var Second: NSCalendarUnit { get } 11 public static var Weekday: NSCalendarUnit { get } 12 public static var WeekdayOrdinal: NSCalendarUnit { get } 13 @available(iOS 4.0, *) 14 public static var Quarter: NSCalendarUnit { get } 15 @available(iOS 5.0, *) 16 public static var WeekOfMonth: NSCalendarUnit { get } 17 @available(iOS 5.0, *) 18 public static var WeekOfYear: NSCalendarUnit { get } 19 @available(iOS 5.0, *) 20 public static var YearForWeekOfYear: NSCalendarUnit { get } 21 @available(iOS 5.0, *) 22 public static var Nanosecond: NSCalendarUnit { get } 23 @available(iOS 4.0, *) 24 public static var Calendar: NSCalendarUnit { get } 25 @available(iOS 4.0, *) 26 public static var TimeZone: NSCalendarUnit { get } 27 // 下面是废弃了的 28 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitEra instead") 29 public static var NSEraCalendarUnit: NSCalendarUnit { get } 30 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitYear instead") 31 public static var NSYearCalendarUnit: NSCalendarUnit { get } 32 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitMonth instead") 33 public static var NSMonthCalendarUnit: NSCalendarUnit { get } 34 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitDay instead") 35 public static var NSDayCalendarUnit: NSCalendarUnit { get } 36 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitHour instead") 37 public static var NSHourCalendarUnit: NSCalendarUnit { get } 38 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitMinute instead") 39 public static var NSMinuteCalendarUnit: NSCalendarUnit { get } 40 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitSecond instead") 41 public static var NSSecondCalendarUnit: NSCalendarUnit { get } 42 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitWeekOfMonth or NSCalendarUnitWeekOfYear, depending on which you mean") 43 public static var NSWeekCalendarUnit: NSCalendarUnit { get } 44 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitWeekday instead") 45 public static var NSWeekdayCalendarUnit: NSCalendarUnit { get } 46 @available(iOS, introduced=2.0, deprecated=8.0, message="Use NSCalendarUnitWeekdayOrdinal instead") 47 public static var NSWeekdayOrdinalCalendarUnit: NSCalendarUnit { get } 48 @available(iOS, introduced=4.0, deprecated=8.0, message="Use NSCalendarUnitQuarter instead") 49 public static var NSQuarterCalendarUnit: NSCalendarUnit { get } 50 @available(iOS, introduced=5.0, deprecated=8.0, message="Use NSCalendarUnitWeekOfMonth instead") 51 public static var NSWeekOfMonthCalendarUnit: NSCalendarUnit { get } 52 @available(iOS, introduced=5.0, deprecated=8.0, message="Use NSCalendarUnitWeekOfYear instead") 53 public static var NSWeekOfYearCalendarUnit: NSCalendarUnit { get } 54 @available(iOS, introduced=5.0, deprecated=8.0, message="Use NSCalendarUnitYearForWeekOfYear instead") 55 public static var NSYearForWeekOfYearCalendarUnit: NSCalendarUnit { get } 56 @available(iOS, introduced=4.0, deprecated=8.0, message="Use NSCalendarUnitCalendar instead") 57 public static var NSCalendarCalendarUnit: NSCalendarUnit { get } 58 @available(iOS, introduced=4.0, deprecated=8.0, message="Use NSCalendarUnitTimeZone instead") 59 public static var NSTimeZoneCalendarUnit: NSCalendarUnit { get } 60 }
8.真机测试的时候出现:dyld: Library not loaded: @rpath/libswiftAVFoundation.dylib...
第一次出现的时候懵逼了,首先到网上去查,结果是检查发布证书过期、设置
为YES、关机重启Xcode什么什么的招数都用了,就差卸载重装Xcode了。
最终发现command+shift+k清理工程即可。
不用问我为啥,我也不知道为啥。
9.高德地图出现 INVALID_USER_SCODE 的 Error
在用高德地图API的时候,还会遇见一个问题,就是总是提示:INVALID_USER_SCODE。其实这个问题主要原因是你的高德地图的AppKey与你的BundleID对应不上。改你的程序或者高德API处的BundleID即可解决问题。或者你可以根据你现在的BundleID直接创一个新的AppKey即可。
10.增加类名前缀
我们都知道,苹果官方的Framework里面都是带类名前缀的,例如Foundation框架下的类名自带NS(NextStep,Jops在创建Objective-C时所在的公司,也是他创建的),UIKit自带UI,CoreGraphics自带CG等等。苹果希望我们通过带类名前缀解决类的命名问题,减少重名的可能性,也增加类的可分类性,替代其他语言里面类重名的有效空间(或许是别的什么名词...)。
如何在我们的工程中自动为类增加前缀名?
Class Prefix:类名前缀。
这样,在创建新的类的时候就会这样:
11.关于项目支持的朝向问题
有时候我们的项目可能需要支持横屏竖屏甚至倒屏,有时候需要取消掉这些功能。如何处理?
在Target中,有这样一项。 Device Orientation:设备朝向
Portrait:正向
Upside Down:上部朝下(也就是反转屏幕、上下颠倒)
Landscape Left:风景朝左(也就是手机头朝左)
Landscape Right:横屏向右
选择你需要的朝向即可。
12.Archive之后.xcarchive文件不显示在iOS Apps对应的App目录下,而是另起Other Items显示,无法Export和Upload To App Store
这个问题很简单,一行设置。不过如果第一次遇到会抓狂的。问题就在于,如果你的项目中引入了子.xcodeproj文件,那你就要这样做:
所有子项目Skip Install设置为YES。同时,你的主项目的该项要保持为NO。再次打包试一下。
13.Export和Upload To App Store一个xcarchive文件时无限停留在Compling Bitcode界面
这个原因也很简单,是因为你允许了Bitcode。Bitcode是是被编译程序的一种中间形式的代码。更安全,但更慢。如果不想要这个,可以这样做:
关了就可以了。
14.UIView的viewWithtag:方法
关于这个方法,其实也没有太多需要解释的内容。我们知道所有的UIView对象都有一个属性:tag(NSInteger)。这个属性没有什么别的意义,仅仅出于一种标识的意义。所有的view的默认tag是0。而对于这个属性,使用最为频繁的也就是viewWithTag:了。这个方法就在是,传入一个NSInteger作为参数,来返回一个包括调用对象自身在内的所有子控件(以及子控件的子控件)中tag为与参数相同的view。并且会优先返回先加入的view。
似乎没什么难理解的,其实我想说的是这个:有考虑过它内部的实现吗?
其实内部的实现很简单,调用了一个递归算法:
1 - (UIView *)viewWithTag:(NSInteger)tag { 2 3 if (self.tag == tag) return self; 4 5 for (UIView *subView in self.subviews) { 6 7 return [subView viewWithTag:tag]; 8 } 9 }
看完了之后,似乎所有关于这个方法的注意事项都能找到解释了。
似乎有些歪题,但其实还是在提醒自己,要好好学习啊 - -
15.ld warning: directory not found for option ...
其实这是个黄色警告,理论上来说改不改都可以。我的问题是出现在Xcode8.2.1上,因为Xcode8不支持插件了,所以我使用了终端来进行Cocoapods导入三方库;但是Cocoapods也时灵时不灵的,在装新的库之后还会出现上述的问题。
我的办法是,复制粘贴源程序一份,在新的程序里面运行,就可以了。因为我的是在编译文件中找不到,clean也不好用,所以采用了这个笨办法。
另外,可以试试下面的方法:
在这里寻找一下你报警的文件名或文件夹名,然后删掉它就可以了。
另外,还需要做另外一个配置:
找到报错的路径,替换成相同格式的路径;如果报错的路径在release中,一样的操作。
16.获取当前项目的项目名
首先,获得infoDictionary:
1 NSDictionary<NSString *, id> *infoDict = [NSBundle mainBundle].infoDictionary;
key是什么的?在这一页:
然后对应写就可以啦。这里能找到info.plist中的任何信息。
另外,取值需要强转一下,否则会有警告。如下:
1 [[NSBundle mainBundle].infoDictionary objectForKey:(NSString *)kCFBundleExecutableKey];