diff --git a/Yep.xcodeproj/project.pbxproj b/Yep.xcodeproj/project.pbxproj index 761db523..3254e634 100644 --- a/Yep.xcodeproj/project.pbxproj +++ b/Yep.xcodeproj/project.pbxproj @@ -76,6 +76,7 @@ 5099B9C41AB9510D002F940B /* RankView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099B9C31AB9510D002F940B /* RankView.swift */; }; 5099B9C71AB99F7B002F940B /* RegisterPickAvatarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099B9C61AB99F7B002F940B /* RegisterPickAvatarViewController.swift */; }; 5099B9C91AB9A7CB002F940B /* CameraPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099B9C81AB9A7CB002F940B /* CameraPreviewView.swift */; }; + 50CDBE3F1ACA58D800459CE0 /* NSFileManager+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE3E1ACA58D800459CE0 /* NSFileManager+Yep.swift */; }; 50E114F41ABBF9CC00F13000 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F31ABBF9CC00F13000 /* Models.swift */; }; 50E114F71ABBFA7000F13000 /* RLMSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F61ABBFA7000F13000 /* RLMSupport.swift */; }; 50E114F91ABC137A00F13000 /* YepServiceSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F81ABC137A00F13000 /* YepServiceSync.swift */; }; @@ -173,6 +174,7 @@ 5099B9C31AB9510D002F940B /* RankView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RankView.swift; path = Views/Rank/RankView.swift; sourceTree = ""; }; 5099B9C61AB99F7B002F940B /* RegisterPickAvatarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RegisterPickAvatarViewController.swift; path = ViewControllers/Register/RegisterPickAvatarViewController.swift; sourceTree = ""; }; 5099B9C81AB9A7CB002F940B /* CameraPreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CameraPreviewView.swift; path = Views/CameraPreview/CameraPreviewView.swift; sourceTree = ""; }; + 50CDBE3E1ACA58D800459CE0 /* NSFileManager+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+Yep.swift"; sourceTree = ""; }; 50E114F31ABBF9CC00F13000 /* Models.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Models.swift; path = Realm/Models.swift; sourceTree = ""; }; 50E114F61ABBFA7000F13000 /* RLMSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RLMSupport.swift; path = Realm/RLMSupport.swift; sourceTree = ""; }; 50E114F81ABC137A00F13000 /* YepServiceSync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepServiceSync.swift; path = Services/YepServiceSync.swift; sourceTree = ""; }; @@ -366,6 +368,7 @@ 5023DE511AB6C51300B3EE96 /* CGRect+Yep.swift */, 5023DE581AB6DBC100B3EE96 /* UIImage+Yep.swift */, 506EC2091AC95BFC00CE42B3 /* UIFont+Yep.swift */, + 50CDBE3E1ACA58D800459CE0 /* NSFileManager+Yep.swift */, ); name = Extensions; sourceTree = ""; @@ -841,6 +844,7 @@ 502AE52E1AB83879005BD199 /* UnderLineTextField.swift in Sources */, 5023DE301AB6861500B3EE96 /* ProfileViewController.swift in Sources */, 50E114F71ABBFA7000F13000 /* RLMSupport.swift in Sources */, + 50CDBE3F1ACA58D800459CE0 /* NSFileManager+Yep.swift in Sources */, 5023DE261AB6856300B3EE96 /* ConversationsViewController.swift in Sources */, 506EC20A1AC95BFC00CE42B3 /* UIFont+Yep.swift in Sources */, 502AE5271AB72D06005BD199 /* YepNetworking.swift in Sources */, diff --git a/Yep/Caches/AvatarCache.swift b/Yep/Caches/AvatarCache.swift index 6530e9d7..22dadbec 100644 --- a/Yep/Caches/AvatarCache.swift +++ b/Yep/Caches/AvatarCache.swift @@ -14,28 +14,28 @@ class AvatarCache { var cache = NSCache() - func roundImageNamed(name: String, ofRadius radius: CGFloat) -> UIImage { - let roundImageKey = "\(name)-\(radius)" - - if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { - return roundImage - - } else { - if let image = UIImage(named: name) { - - let roundImage = image.roundImageOfRadius(radius) - - cache.setObject(roundImage, forKey: roundImageKey) - - return roundImage - } - } - - return defaultRoundAvatarOfRadius(radius) - } +// func roundImageNamed(name: String, ofRadius radius: CGFloat) -> UIImage { +// let roundImageKey = "round-\(name)-\(radius)" +// +// if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { +// return roundImage +// +// } else { +// if let image = UIImage(named: name) { +// +// let roundImage = image.roundImageOfRadius(radius) +// +// cache.setObject(roundImage, forKey: roundImageKey) +// +// return roundImage +// } +// } +// +// return defaultRoundAvatarOfRadius(radius) +// } func defaultRoundAvatarOfRadius(radius: CGFloat) -> UIImage { - let facelessRouncImageKey = "faceless-\(radius)" + let facelessRouncImageKey = "round-faceless-\(radius)" if let roundImage = cache.objectForKey(facelessRouncImageKey) as? UIImage { return roundImage @@ -51,26 +51,26 @@ class AvatarCache { } } - func roundImageFromURL(url: NSURL, ofRadius radius: CGFloat, completion: (UIImage) -> ()) { - let roundImageKey = "\(url.hashValue)" - - if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { - completion(roundImage) - - } else { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { - if let data = NSData(contentsOfURL: url) { - let image = UIImage(data: data)! - - let roundImage = image.roundImageOfRadius(radius) - - self.cache.setObject(roundImage, forKey: roundImageKey) - - completion(roundImage) - } - } - } - } +// func roundImageFromURL(url: NSURL, ofRadius radius: CGFloat, completion: (UIImage) -> ()) { +// let roundImageKey = "round-\(url.hashValue)" +// +// if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { +// completion(roundImage) +// +// } else { +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { +// if let data = NSData(contentsOfURL: url) { +// let image = UIImage(data: data)! +// +// let roundImage = image.roundImageOfRadius(radius) +// +// self.cache.setObject(roundImage, forKey: roundImageKey) +// +// completion(roundImage) +// } +// } +// } +// } func roundAvatarWithAvatarURLString(avatarURLString: String, withRadius radius: CGFloat, completion: (UIImage) -> ()) { if avatarURLString.isEmpty { @@ -80,7 +80,7 @@ class AvatarCache { } if let url = NSURL(string: avatarURLString) { - let roundImageKey = "\(url.hashValue)" + let roundImageKey = "round-\(url.hashValue)" // 先看看缓存 if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { @@ -91,15 +91,17 @@ class AvatarCache { let predicate = NSPredicate(format: "avatarURLString = %@", avatarURLString) if let avatar = Avatar.objectsWithPredicate(predicate).firstObject() as? Avatar { - let image = UIImage(data: avatar.imageData)! + if + let avatarFileURL = NSFileManager.yepAvatarURLWithName(avatar.avatarFileName), + let image = UIImage(contentsOfFile: avatarFileURL.path!) { + let roundImage = image.roundImageOfRadius(radius) - let roundImage = image.roundImageOfRadius(radius) + self.cache.setObject(roundImage, forKey: roundImageKey) - self.cache.setObject(roundImage, forKey: roundImageKey) + completion(roundImage) - completion(roundImage) - - return + return + } } // 没办法,下载吧 @@ -109,8 +111,6 @@ class AvatarCache { // TODO 裁减 image - let imageData = UIImageJPEGRepresentation(image, 0.8) - dispatch_async(dispatch_get_main_queue()) { let realm = RLMRealm.defaultRealm() @@ -120,11 +120,15 @@ class AvatarCache { var avatar = Avatar.objectsWithPredicate(predicate).firstObject() as? Avatar if avatar == nil { - let newAvatar = Avatar() - newAvatar.avatarURLString = avatarURLString - newAvatar.imageData = imageData + let avatarFileName = NSUUID().UUIDString - realm.addObject(newAvatar) + if let avatarURL = NSFileManager.saveAvatarImage(image, withName: avatarFileName) { + let newAvatar = Avatar() + newAvatar.avatarURLString = avatarURLString + newAvatar.avatarFileName = avatarFileName + + realm.addObject(newAvatar) + } } realm.commitWriteTransaction() @@ -154,7 +158,7 @@ class AvatarCache { } if let url = NSURL(string: user.avatarURLString) { - let roundImageKey = "\(url.hashValue)" + let roundImageKey = "round-\(url.hashValue)" // 先看看缓存 if let roundImage = cache.objectForKey(roundImageKey) as? UIImage { @@ -165,15 +169,18 @@ class AvatarCache { // 再看看是否已下载 if let avatar = user.avatar { if avatar.avatarURLString == user.avatarURLString { - let image = UIImage(data: avatar.imageData)! - let roundImage = image.roundImageOfRadius(radius) + if + let avatarFileURL = NSFileManager.yepAvatarURLWithName(avatar.avatarFileName), + let image = UIImage(contentsOfFile: avatarFileURL.path!) { + let roundImage = image.roundImageOfRadius(radius) - self.cache.setObject(roundImage, forKey: roundImageKey) + self.cache.setObject(roundImage, forKey: roundImageKey) - completion(roundImage) + completion(roundImage) - return + return + } } else { // 换了 Avatar,删除旧的 // TODO: need test @@ -196,8 +203,6 @@ class AvatarCache { // TODO 裁减 image - let imageData = UIImageJPEGRepresentation(image, 0.8) - dispatch_async(dispatch_get_main_queue()) { let realm = RLMRealm.defaultRealm() @@ -207,11 +212,16 @@ class AvatarCache { var avatar = Avatar.objectsWithPredicate(predicate).firstObject() as? Avatar if avatar == nil { - let newAvatar = Avatar() - newAvatar.avatarURLString = user.avatarURLString - newAvatar.imageData = imageData + let avatarFileName = NSUUID().UUIDString + if let avatarURL = NSFileManager.saveAvatarImage(image, withName: avatarFileName) { + let newAvatar = Avatar() + newAvatar.avatarURLString = user.avatarURLString + newAvatar.avatarFileName = avatarFileName - avatar = newAvatar + realm.addObject(newAvatar) + + avatar = newAvatar + } } if let avatar = avatar { @@ -234,6 +244,8 @@ class AvatarCache { completion(defaultRoundAvatarOfRadius(radius)) } } + } + diff --git a/Yep/NSFileManager+Yep.swift b/Yep/NSFileManager+Yep.swift new file mode 100644 index 00000000..220109cb --- /dev/null +++ b/Yep/NSFileManager+Yep.swift @@ -0,0 +1,49 @@ +// +// NSFileManager+Yep.swift +// Yep +// +// Created by NIX on 15/3/31. +// Copyright (c) 2015年 Catch Inc. All rights reserved. +// + +import UIKit + +extension NSFileManager { + class func yepCachesURL() -> NSURL { + return NSFileManager.defaultManager().URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: nil)! + } + + class func yepAvatarCachesURL() -> NSURL? { + + let fileManager = NSFileManager.defaultManager() + + let avatarCachesURL = yepCachesURL().URLByAppendingPathComponent("avatar_caches", isDirectory: true) + + if fileManager.createDirectoryAtURL(avatarCachesURL, withIntermediateDirectories: true, attributes: nil, error: nil) { + return avatarCachesURL + } + + return nil + } + + class func yepAvatarURLWithName(name: String) -> NSURL? { + + if let avatarCachesURL = yepAvatarCachesURL() { + return avatarCachesURL.URLByAppendingPathComponent("\(name).jpg") + } + + return nil + } + + class func saveAvatarImage(avatarImage: UIImage, withName name: String) -> NSURL? { + + if let avatarURL = yepAvatarURLWithName(name) { + let imageData = UIImageJPEGRepresentation(avatarImage, 0.8) + if NSFileManager.defaultManager().createFileAtPath(avatarURL.path!, contents: imageData, attributes: nil) { + return avatarURL + } + } + + return nil + } +} diff --git a/Yep/Realm/Models.swift b/Yep/Realm/Models.swift index d01937c4..09f29a77 100644 --- a/Yep/Realm/Models.swift +++ b/Yep/Realm/Models.swift @@ -26,7 +26,7 @@ enum UserFriendState: Int { class Avatar: RLMObject { dynamic var avatarURLString: String = "" - dynamic var imageData: NSData = NSData() + dynamic var avatarFileName: String = "" var user: User? { let users = linkingObjectsOfClass("User", forProperty: "avatar") as! [User]