0%

mac OS配置JAVA环境

  • 下载安装最新版的JDK安装包:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html,安装完成后查看下Java的版本后面配置要用到:java -version

    1
    2
    3
    4
    admindeMacBook-Pro:未命名文件夹 admin$ java -version
    java version "1.8.0_144"
    Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
    Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
  • 配置环境变量:在命令行中打开sudo vim ~/.bash_profile,在文件后面加入下面内容:

    1
    2
    3
    export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home" 
    export PATH="$JAVA_HOME/bin:$PATH"
    export CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"

    note:/jdk1.8.0_144.jdk里面的版本字符串需要替换为上面提到的版本字符串.
    完成后保存,并使用source ~/.bash_profile应用该变更。

测试某个网址是否使用https:
nscurl --ats-diagnostics --verbose https://www.baidu.com

Swift对象拷贝

方法一:实现NSCopying协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Resume: NSObject, NSCopying {
var name: String
var sex: String?
var age: String?
var timeArea: String?
var company: String?

//必须要有一个required的初始化方法
required init(name: String) {
self.name = name
}

func copy(with zone: NSZone? = nil) -> Any {
let obj = type(of: self).init(name: name)
obj.sex = sex
obj.age = age
obj.timeArea = timeArea
obj.company = company
return obj
}
}

使用:
let ben = Resume.init(name: "本初")
var shu = ben.copy() as! Resume

方法二:实现自定义拷贝协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protocol Copyable {
func copied() -> Self
}

class Book: Copyable {
var name: String
var author: String?
var publish: String?

//必须要有一个required的初始化方法
required init(name: String) {
self.name = name
}

func copied() -> Self {
let obj = type(of: self).init(name: name)
obj.name = name
obj.author = author
obj.publish = publish
return obj
}
}

使用:
let sanguo = Book.init(name: "three of kingdom")
let book = sanguo.copied()

Swift实现removeObject

如果类没有继承自NSObject,那么类必须要实现Equatable协议.否则不需要.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Observer {
var name: String!
var subject: Subject!
func observer(name: String, subject: Subject) {
self.name = name
self.subject = subject
}

func update() {

}
}

extension Observer: Equatable {
static func ==(lhs: Observer, rhs: Observer) -> Bool {
if lhs === rhs { //地址相等. ps:"=="值相等.
return true
} else {
return false
}
}
}

然后在通过扩展给Array增加一个removeObject(object: Element)方法:

1
2
3
4
5
6
7
extension Array where Element: Equatable {
mutating func removeObject(object: Element) {
if let index = index(of: object) {
remove(at: index)
}
}
}

由于Array是结构体类型,而removeObject函数会改变结构体的值,所以该函数需要添加mutating关键字.“Notice the use of the mutating keyword in the declaration of SimpleStructure to mark a method that modifies the structure. The declaration of SimpleClass doesn’t need any of its methods marked as mutating because methods on a class can always modify the class.”

Swift里addTarget函数里的Selector参数和OC的不太一样.
open func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControlEvents)
根据Selector的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public struct Selector : ExpressibleByStringLiteral {

/// Create a selector from a string.
public init(_ str: String)

/// Create an instance initialized to `value`.
public init(unicodeScalarLiteral value: String)

/// Construct a selector from `value`.
public init(extendedGraphemeClusterLiteral value: String)

/// Create an instance initialized to `value`.
public init(stringLiteral value: String)
}

它是一个结构体,并遵守ExpressibleByStringLiteral协议,因此可以直接传递一个字面值字符串.
不过这个字符串需要遵循一定的规则:

  1. 如果函数没有参数,则字符串的格式为”函数名”.
  2. 如果函数有参数但省略了参数标签,则字符串的格式为”函数名:”.
  3. 如果函数有参数并且没有省略参数标签,则字符串的格式为”函数名With参数标签:”.ps:如果函数使用的是默认参数标签即使用参数名称作为参数标签的,那么字符串的格式为”函数名With参数名称:”

举个例子:

  1. 没有参数
    1
    2
    func numberSliderChanged() -> Void {
    }
    对应写法:numberSlider.addTarget(self, action: "numberSliderChanged", for: .valueChanged)
  2. 省略参数标签
    1
    2
    3
    func numberSliderChanged(_ sender: UISlider) -> Void {
    print("---", sender.value)
    }
    对应写法:numberSlider.addTarget(self, action: "numberSliderChanged:", for: .valueChanged)
  3. 写明了参数标签slider.
    1
    2
    3
    func numberSliderChanged(slider sender: UISlider) -> Void {
    print(sender.value)
    }
    对应写法:numberSlider.addTarget(self, action: "numberSliderChangedWithSlider:", for: .valueChanged)
  4. 使用默认参数标签
    1
    2
    3
    func numberSliderChanged(sender: UISlider) -> Void {
    print("sds", sender.value)
    }
    对应写法:numberSlider.addTarget(self, action: "numberSliderChangedWithSender:", for: .valueChanged)

然而这种写法已经废弃,目前swift3.1推荐的是使用#selector,因此上述4写法等价于:
numberSlider.addTarget(self, action: #selector(numberSliderChanged(sender:)), for: .valueChanged).
当然你也可以传递一个Selector类型的变量:
numberSlider.addTarget(self, action: Selector.init(stringLiteral: "numberSliderChangedWithSender:"), for: .valueChanged).不过这种写法依然不是推荐的写法.

协议

可选实现

Swift里标记某个方法为可选实现时,需要在协议前添加@objc,并且在可选方法前添加@objc optional.其实也是为了跟OC兼容.
eg:

1
2
3
4
5
6
7
8
9
@objc protocol Iterator {
func first() -> AnyObject?

func next() -> AnyObject?

@objc optional func isDone() -> Bool

func currentItem() -> AnyObject?
}

判断某个实例是否实现了协议里的可选方法:

1
2
3
4
5
if i.isDone?() != nil {
print("\(i) 实现了方法isDone")
} else {
print("\(i) 没实现方法isDone")
}

因为isDone是可选实现方法,所以调用时需要加?,这样就转为optional chaining处理,如果方法的返回值不为nil,则说明对象实现了协议的可选实现方法.

Q:在用 Cocoapods 做第三方开源库管理的时候,有时候发现查找到的第三方库版本低于github上仓库的最新release版本.
A:执行pod update更新本地仓库,完成后,即可搜索到指定的第三方库.

Q:在使用了pod setup之后,发现好长时间都没有变化,无法从终端上获取pod setup的执行情况.
A:这时候可以command+N新建一个窗口,通过sudo ls用管理员权限查看目录,然后cd .cocoapods文件夹,输入du -sh命令查看文件夹大小变化,从而确定pod setup的运行情况.

note:在Podfile文件中的platform :ios, '7.0',如果你设置的iOS系统过低,可能有的第三方库会下载不下来.所以还是要看一下第三方库的最低版本支持说明.

Q:RuntimeError - [Xcodeproj] Unknown object version.然后是一大堆错误日志.不管是重新从svn checkout一份新的还是怎样,pod install都不能成功.
A:一种解决办法:重新安装cocoapods.

Q:pod search xxx,总是失败,提示CDN: trunk URL couldn’t be downloaded … Response: SSL connect error

1
2
3
[!] CDN: trunk Repo update failed - 2 error(s):
CDN: trunk URL couldn't be downloaded: https://cdn.jsdelivr.net/cocoa/Specs/7/1/d/lottie-ios/4.4.0/lottie-ios.podspec.json Response: SSL connect error
CDN: trunk URL couldn't be downloaded: https://cdn.jsdelivr.net/cocoa/Specs/7/1/d/lottie-ios/4.4.1/lottie-ios.podspec.json Response: SSL connect error

解决办法:

The workaround to get working locally during this outage or CDN issue - guessing a DNS change or something?:

1
pod repo remove trunk

In Podfile

阅读全文 »

更新ruby后,pod install出错.

xuequandeiMac:KingDynastyGaming xuequan$ pod install
提示:

1
/Library/Ruby/Site/2.0.0/rubygems.rb:270:in `find_spec_for_exe': can't find gem cocoapods (>= 0.a) (Gem::GemNotFoundException) from /Library/Ruby/Site/2.0.0/rubygems.rb:298:in `activate_bin_path' from /usr/local/bin/pod:22:in `<main>'

解决办法:卸载cocoapods后重新安装

  1. sudo gem uninstall cocoapods
  2. gem install cocoapods
  3. pod install

多个targets的Podfile写法

项目里面添加了多个target,每次pod install后,其他target就出现找不到#import <AFNetworking.h>这样的编译错误,花了三个多小时才找到了原因:是因为Podfile文件只给其中一个target配置了,所以导致了上述的问题.
正确写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
platform :ios, '8.0'

def shared_pods
pod 'AFNetworking', '3.1.0'
pod 'MJExtension', '3.0.13'
pod 'SDWebImage', '4.0.0'
pod 'FMDB', '2.6.2'
pod 'MJRefresh', '3.1.12'
pod 'SDCycleScrollView', '1.66'
pod 'Bugly', '2.4.8'
pod 'MBProgressHUD', '1.0.0'
pod 'Masonry', '1.0.2'
pod 'IQKeyboardManager', '4.0.9'
pod 'TZImagePickerController', '1.7.9'
pod 'RealReachability', '1.1.9'
pod 'MMDrawerController', '0.6.0'
pod 'UMengAnalytics-NO-IDFA'
end

target 'xxx1' do
shared_pods
end

target 'xxx2' do
shared_pods
end

参考:CocoaPods使用注意事项

高度的计算

通过从可重用队列里出列一个cell,并将该cell配置好要展示的数据后(ps:在使用时如果有一些会影响cell高度的代码没有包括在配置block里将导致计算不准),开始计算cell的高度:

  1. 给cell添加约束:
    NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];
    对于10.2以上系统还需添加cell上下左右的约束:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if (isSystemVersionEqualOrGreaterThen10_2) {
    // To avoid confilicts, make width constraint softer than required (1000)
    widthFenceConstraint.priority = UILayoutPriorityRequired - 1;

    // Build edge constraints
    NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
    NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeRight multiplier:1.0 constant:accessroyWidth];
    NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
    NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
    edgeConstraints = @[leftConstraint, rightConstraint, topConstraint, bottomConstraint];
    [cell addConstraints:edgeConstraints];
    }
  2. 调用系统APIsystemLayoutSizeFittingSize计算出高度:fittingHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

  3. 移除之前添加的约束:

    1
    2
    3
    4
    [cell.contentView removeConstraint:widthFenceConstraint];
    if (isSystemVersionEqualOrGreaterThen10_2) {
    [cell removeConstraints:edgeConstraints];
    }

最终得到cell的高度.

高度缓存的实现

通过给UITableView增加一个类别(FDIndexPathHeightCache):

1
2
3
4
@interface UITableView (FDIndexPathHeightCache)
/// Height cache by index path. Generally, you don't need to use it directly.
@property (nonatomic, strong, readonly) FDIndexPathHeightCache *fd_indexPathHeightCache;
@end

类别里有一个FDIndexPathHeightCache类型的属性fd_indexPathHeightCache是只读的,用于操作缓存:设置缓存,取出缓存,清除缓存,查询某个缓存是否存在等.FDIndexPathHeightCache内部扩展定义了一个用于保存缓存的二维数组.以后取缓存时是从该二维数组取得.默认高度是-1,即该行cell还未缓存高度.

缓存高度的清除时机

定义了一个类别FDIndexPathHeightCacheInvalidation,该类别通过method swizzle交换了一些系统方法的实现.

阅读全文 »