Commit a7703dda authored by shenyong's avatar shenyong

111

parent 3bd07415
......@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
042EF7462DD4A3F90028DE2C /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 042EF7452DD4A3F90028DE2C /* Kingfisher */; };
0496DEF32D9E3F58005B2834 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915D2D9D68AD00055CEB /* WidgetKit.framework */; };
0496DEF42D9E3F58005B2834 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915F2D9D68AD00055CEB /* SwiftUI.framework */; };
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0496DEF22D9E3F57005B2834 /* widgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
......@@ -159,6 +160,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
042EF7462DD4A3F90028DE2C /* Kingfisher in Frameworks */,
3A00E856852A8783E544CD7D /* Pods_PhoneManager.framework in Frameworks */,
04BBB4E62DC0748F00D7E3AB /* StoreKit.framework in Frameworks */,
04EC294B2DD33B480049739A /* GoogleSignIn in Frameworks */,
......@@ -318,6 +320,7 @@
minimizedProjectReferenceProxies = 1;
packageReferences = (
04EC26182DD33B070049739A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */,
042EF7442DD4A3780028DE2C /* XCRemoteSwiftPackageReference "Kingfisher" */,
);
preferredProjectObjectVersion = 77;
productRefGroup = EB388E5C2D8A61A800629B0D /* Products */;
......@@ -838,6 +841,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
042EF7442DD4A3780028DE2C /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 8.3.2;
};
};
04EC26182DD33B070049739A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/google/GoogleSignIn-iOS";
......@@ -849,6 +860,11 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
042EF7452DD4A3F90028DE2C /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = 042EF7442DD4A3780028DE2C /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
};
04EC294A2DD33B480049739A /* GoogleSignIn */ = {
isa = XCSwiftPackageProductDependency;
package = 04EC26182DD33B070049739A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */;
......
{
"originHash" : "68aa00e3cba36db2e0a76f54dbc84d1f079d8aa9a19bfa9fce02d6286bd620b7",
"originHash" : "c64907f28a6f12cd9166d202e75e2e3776dc750a2e196ae17a655106dc8ba134",
"pins" : [
{
"identity" : "app-check",
......@@ -55,6 +55,15 @@
"version" : "4.1.1"
}
},
{
"identity" : "kingfisher",
"kind" : "remoteSourceControl",
"location" : "https://github.com/onevcat/Kingfisher.git",
"state" : {
"revision" : "7deda23bbdca612076c5c315003d8638a08ed0f1",
"version" : "8.3.2"
}
},
{
"identity" : "promises",
"kind" : "remoteSourceControl",
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -40,7 +40,7 @@ class BaseNavView:UIView {
let titleLabel:UILabel = UILabel()
titleLabel.font = UIFont.systemFont(ofSize: 18.RW(), weight: .medium)
titleLabel.textColor = UIColor.colorWithHex(hexStr: whiteColor)
titleLabel.textColor = .black
titleLabel.textAlignment = .center
return titleLabel
}()
......@@ -107,7 +107,7 @@ class BaseNavViewModel {
var callBack: callBack<Any> = {text in }
var title:String = "Title" {
var title:String = "" {
didSet {
callBack("title")
......
......@@ -400,6 +400,8 @@ extension PhotoManager{
// }
// }
func getImage(localIdentifier: String, targetSize: CGSize = PHImageManagerMaximumSize, completion: @escaping (UIImage?) -> Void) {
Task {
// 先检查缓存
......
import UIKit
import Photos
// 图片缓存管理(单例)
private let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
// 关联对象键,用于存储当前请求的 localIdentifier
private struct AssociatedKeys {
static var currentRequestID = "currentRequestID"
static var currentAssetIdentifier = "currentAssetIdentifier"
}
// 当前请求 ID
private var currentRequestID: PHImageRequestID? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.currentRequestID) as? PHImageRequestID
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.currentRequestID, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 当前请求的 asset identifier
private var currentAssetIdentifier: String? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.currentAssetIdentifier) as? String
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.currentAssetIdentifier, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
// 加载图片的主方法
func loadImage(
withLocalIdentifier identifier: String,
targetSize: CGSize = PHImageManagerMaximumSize,
placeholder: UIImage? = nil,
completion: ((UIImage?) -> Void)? = nil
) {
// 1. 先取消当前进行中的请求
if let requestID = currentRequestID {
PHImageManager.default().cancelImageRequest(requestID)
}
// 2. 设置占位图
image = placeholder
// 3. 检查缓存
if let cachedImage = imageCache.object(forKey: identifier as NSString) {
self.image = cachedImage
completion?(cachedImage)
return
}
// 4. 存储当前请求信息
currentRequestID = nil
currentAssetIdentifier = identifier
// 5. 获取 PHAsset
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil)
guard let asset = fetchResult.firstObject else {
completion?(nil)
return
}
// 6. 配置图片请求选项
let options = PHImageRequestOptions()
options.version = .current
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
options.resizeMode = .exact
// 7. 请求图片
currentRequestID = PHImageManager.default().requestImage(
for: asset,
targetSize: targetSize,
contentMode: .aspectFit,
options: options
) { [weak self] image, info in
guard let self = self else { return }
// 8. 验证请求是否匹配(避免复用导致的错乱)
if self.currentAssetIdentifier != identifier {
return
}
// 9. 处理结果
if let image = image {
// 缓存图片
imageCache.setObject(image, forKey: identifier as NSString)
// 更新 UI
DispatchQueue.main.async {
self.image = image
completion?(image)
}
} else {
DispatchQueue.main.async {
completion?(nil)
}
}
// 10. 重置请求状态
self.currentRequestID = nil
self.currentAssetIdentifier = nil
}
}
// 取消当前图片请求
func cancelImageRequest() {
if let requestID = currentRequestID {
PHImageManager.default().cancelImageRequest(requestID)
currentRequestID = nil
currentAssetIdentifier = nil
}
}
// 命名空间
struct AssetLoader {
fileprivate weak var imageView: UIImageView?
}
var asset: AssetLoader {
return AssetLoader(imageView: self)
}
}
extension UIImageView.AssetLoader {
func load(
withLocalIdentifier identifier: String,
targetSize: CGSize = PHImageManagerMaximumSize,
placeholder: UIImage? = nil,
completion: ((UIImage?) -> Void)? = nil
) {
imageView?.loadImage(
withLocalIdentifier: identifier,
targetSize: targetSize,
placeholder: placeholder,
completion: completion
)
}
// 圆角图片扩展
func loadRounded(
withLocalIdentifier identifier: String,
targetSize: CGSize = PHImageManagerMaximumSize,
cornerRadius: CGFloat? = nil,
placeholder: UIImage? = nil
) {
load(
withLocalIdentifier: identifier,
targetSize: targetSize,
placeholder: placeholder
) { image in
DispatchQueue.main.async {
if let radius = cornerRadius {
self.imageView?.layer.cornerRadius = radius
} else {
self.imageView?.layer.cornerRadius = (self.imageView?.bounds.width ?? 0) / 2
}
self.imageView?.layer.masksToBounds = true
self.imageView?.image = image
}
}
}
}
......@@ -30,20 +30,24 @@ class ImageCollectionCell:UICollectionViewCell {
didSet {
DispatchQueue.global().async {[weak self] in
guard let self else {return}
let image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: model.asset.localIdentifier)
// DispatchQueue.global().async {[weak self] in
//
// guard let self else {return}
//
// let image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: model.asset.localIdentifier)
//
// DispatchQueue.main.async {[weak self] in
//
// guard let self else {return}
//
// backImageView?.image = image
//
// }
// }\
backImageView?.asset.load(withLocalIdentifier: model.asset.localIdentifier,placeholder: UIImage.init(named: "othermoren"))
DispatchQueue.main.async {[weak self] in
guard let self else {return}
backImageView?.image = image
}
}
}
......
......@@ -11,24 +11,19 @@ class MaintaiDetailViewController: BaseViewController {
var dataSource:[[AssetModel]] = []
var tempUrl:URL?
var selectAsset:[[AssetModel]] = []
// var tempUrl:URL?
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(titleView.snp.bottom)
}
if let asset = PhotoManager.shared.videoAssets.first{
PhotoManager.shared.getVideoURL(localIdentifier: asset.localIdentifier, completion: {[weak self] url in
guard let weakSelf = self else { return }
weakSelf.tempUrl = url
weakSelf.tableView.reloadData()
})
}
}
......@@ -44,12 +39,23 @@ class MaintaiDetailViewController: BaseViewController {
return tableView
}()
lazy var maintaiBottomView:MaintaiBottomView = {
let maintaiBottomView = Bundle.main.loadNibNamed("MaintaiBottomView", owner: nil)?.last as! MaintaiBottomView
maintaiBottomView.frame = CGRect(x: 0, y: ScreenH, width: ScreenW, height: 78+kSafeAreaInsets.bottom)
return maintaiBottomView
}()
lazy var maintaiTipsAlertView:MaintaiTipsAlertView = {
let maintaiTipsAlertView = Bundle.main.loadNibNamed("MaintaiTipsAlertView", owner: nil)?.last as! MaintaiTipsAlertView
return maintaiTipsAlertView
}()
}
extension MaintaiDetailViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3 //dataSource.count
return dataSource.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
......@@ -57,18 +63,24 @@ extension MaintaiDetailViewController:UITableViewDelegate,UITableViewDataSource{
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0{
if dataSource[indexPath.row].first?.mediaType == 1,dataSource[indexPath.row].count > 1{
let cell = tableView.dequeueReusableCell(withIdentifier: "MaintaiDetailTableViewCell") as! MaintaiDetailTableViewCell
cell.source = dataSource[indexPath.row]
return cell
}
if indexPath.row == 1{
let cell = tableView.dequeueReusableCell(withIdentifier: "MaintaiDetialVideoCell") as! MaintaiDetialVideoCell
cell.configure(with: tempUrl)
if dataSource[indexPath.row].first?.mediaType == 1,dataSource[indexPath.row].count == 1{
let cell = tableView.dequeueReusableCell(withIdentifier: "MaintaiDetailPicCell") as! MaintaiDetailPicCell
cell.model = dataSource[indexPath.row].first
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "MaintaiDetailPicCell") as! MaintaiDetailPicCell
let cell = tableView.dequeueReusableCell(withIdentifier: "MaintaiDetialVideoCell") as! MaintaiDetialVideoCell
cell.model = dataSource[indexPath.row].first
return cell
}
}
......@@ -9,19 +9,19 @@ import UIKit
class MaintainViewListController: BaseViewController {
var selectStatus:[Int] = [0,0,0,0,0,0,0,0,0,0,0]{
didSet{
if selectStatus.contains(1){
maintaiBottomView.show()
}else{
maintaiBottomView.disMiss()
}
}
}
var selectAsset:[[AssetModel]] = []
var viewModel:MaintaiViewModel = MaintaiViewModel()
override func viewDidLoad() {
super.viewDidLoad()
titleView.model.title = "Keep List"
configUI()
getData()
}
func configUI(){
view.addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
......@@ -29,10 +29,11 @@ class MaintainViewListController: BaseViewController {
}
maintaiTipsAlertView.confirmBlock = {[weak self] in
// guard let weakSelf = self else { return }
guard let weakSelf = self else { return }
weakSelf.removeFromKeep()
weakSelf.maintaiTipsAlertView.disMiss()
}
maintaiBottomView.removeMaintaiBlock = {[weak self] in
guard let weakSelf = self else { return }
weakSelf.maintaiTipsAlertView.show()
......@@ -40,6 +41,30 @@ class MaintainViewListController: BaseViewController {
}
func removeFromKeep(){
let ids = selectAsset.flatMap{$0}.compactMap{$0.localIdentifier}
if GroupDatabase.shared.batchDelete(localIdentifiers: ids){
getData()
}
}
func getData(){
viewModel.refreshData {[weak self] in
guard let self = self else { return }
if self.viewModel.souces.isEmpty {
self.view.addSubview(self.maintaiEmptyView)
} else {
self.maintaiEmptyView.removeFromSuperview()
}
self.collectionView.reloadData()
}
}
lazy var collectionView:UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: (ScreenW-35)/2.0, height: (ScreenW-35)/2.0)
......@@ -67,31 +92,60 @@ class MaintainViewListController: BaseViewController {
let maintaiTipsAlertView = Bundle.main.loadNibNamed("MaintaiTipsAlertView", owner: nil)?.last as! MaintaiTipsAlertView
return maintaiTipsAlertView
}()
lazy var maintaiEmptyView:MaintaiEmptyView = {
let maintaiEmptyView = Bundle.main.loadNibNamed("MaintaiEmptyView", owner: nil)?.last as! MaintaiEmptyView
maintaiEmptyView.frame = CGRectMake(0, 140, ScreenW, 330)
return maintaiEmptyView
}()
}
extension MaintainViewListController:UICollectionViewDataSource,UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
return selectStatus.count
return viewModel.souces.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MaintainViewListCell", for: indexPath) as! MaintainViewListCell
let isSelect = selectAsset.contains(viewModel.souces[indexPath.row])
cell.reloadData(viewModel.souces[indexPath.row], isSelect:isSelect)
cell.selectBlock = {[weak self] in
guard let weakSelf = self else { return }
weakSelf.view.addSubview(weakSelf.maintaiBottomView)
weakSelf.selectStatus[indexPath.row] = weakSelf.selectStatus[indexPath.row] == 1 ? 0 : 1
if let index = weakSelf.selectAsset.firstIndex(where: {
$0 == weakSelf.viewModel.souces[indexPath.row]
}) {
// 包含:移除元素
weakSelf.selectAsset.remove(at: index)
} else {
// 不包含:添加元素
weakSelf.selectAsset.append(weakSelf.viewModel.souces[indexPath.row])
}
weakSelf.dealPickAssetModel()
weakSelf.collectionView.reloadData()
// weakSelf.collectionView.reloadItems(at: [IndexPath(row: indexPath.row, section: indexPath.section)])
}
cell.selectBtn.isSelected = selectStatus[indexPath.row] == 1
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
let vc = MaintaiDetailViewController()
vc.dataSource = viewModel.souces
vc.selectAsset = selectAsset
navigationController?.pushViewController(vc, animated: true)
}
func dealPickAssetModel(){
if selectAsset.count > 0{
let count = selectAsset.flatMap{$0}.count
maintaiBottomView.numberL.text = "\(count)"
maintaiBottomView.show()
}else{
maintaiBottomView.disMiss()
}
}
}
//
// MaintaiViewModel.swift
// PhoneManager
//
// Created by edy on 2025/5/14.
//
import Foundation
class MaintaiViewModel{
var dataSouece:[String:[AssetModel]] = [:]
var souces:[[AssetModel]] = []
func getMaintaiData(complect:() ->Void){
let list = GroupDatabase.shared.queryAll()
list.forEach { (localIdentifier: String, assetSize: Double, createDate: Date, mediaType: Int, groupId: String) in
if dataSouece[groupId] == nil {
dataSouece[groupId] = []
}
dataSouece[groupId]?.append(AssetModel(localIdentifier: localIdentifier, assetSize: assetSize, createDate: createDate, mediaType: mediaType))
}
souces = dataSouece.values.map{$0}
complect()
}
func refreshData(completion: @escaping () -> Void) {
dataSouece.removeAll()
souces.removeAll()
// 重新加载数据
getMaintaiData(complect: completion)
}
}
......@@ -16,13 +16,13 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="neb-y6-gXk">
<rect key="frame" x="13" y="26.333333333333329" width="11" height="27.666666666666671"/>
<rect key="frame" x="18" y="26.333333333333329" width="11" height="27.666666666666671"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
<color key="textColor" red="0.066666666669999999" green="0.066666666669999999" blue="0.066666666669999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Selected picture" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3B9-bn-apH">
<rect key="frame" x="48" y="33" width="97" height="14.333333333333336"/>
<rect key="frame" x="47" y="33" width="97" height="14.333333333333336"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="12"/>
<color key="textColor" red="0.066666666669999999" green="0.066666666669999999" blue="0.066666666669999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
......@@ -34,8 +34,9 @@
<constraint firstAttribute="width" constant="174" id="EG9-xJ-hJZ"/>
<constraint firstAttribute="height" constant="40" id="ddO-RT-eKr"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="No retention"/>
<state key="normal" title="Un-keep Selected"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="10"/>
......@@ -51,9 +52,9 @@
<constraints>
<constraint firstItem="7oF-X4-Rdp" firstAttribute="trailing" secondItem="XE9-Mv-kN1" secondAttribute="trailing" constant="16" id="4te-5s-zea"/>
<constraint firstItem="XE9-Mv-kN1" firstAttribute="top" secondItem="CTb-Ac-3zM" secondAttribute="top" constant="20" id="Cog-R5-MKA"/>
<constraint firstItem="neb-y6-gXk" firstAttribute="leading" secondItem="CTb-Ac-3zM" secondAttribute="leading" constant="13" id="NOG-dJ-CwV"/>
<constraint firstItem="neb-y6-gXk" firstAttribute="leading" secondItem="CTb-Ac-3zM" secondAttribute="leading" constant="18" id="NOG-dJ-CwV"/>
<constraint firstItem="XE9-Mv-kN1" firstAttribute="centerY" secondItem="neb-y6-gXk" secondAttribute="centerY" id="fgn-3P-w8I"/>
<constraint firstItem="3B9-bn-apH" firstAttribute="leading" secondItem="neb-y6-gXk" secondAttribute="trailing" constant="24" id="mqv-bV-sLV"/>
<constraint firstItem="3B9-bn-apH" firstAttribute="leading" secondItem="neb-y6-gXk" secondAttribute="trailing" constant="18" id="mqv-bV-sLV"/>
<constraint firstItem="3B9-bn-apH" firstAttribute="centerY" secondItem="neb-y6-gXk" secondAttribute="centerY" id="p28-zT-gUD"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
......
......@@ -9,7 +9,7 @@ import UIKit
class MaintaiDetailImageCell: UICollectionViewCell {
@IBOutlet weak var num: UILabel!
@IBOutlet weak var coverImage: UIImageView!
var selectBtn:UIButton!
......@@ -17,28 +17,22 @@ class MaintaiDetailImageCell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
setUI()
coverImage.layer.cornerRadius = 12
coverImage.layer.masksToBounds = true
}
private func setUI(){
selectBtn = UIButton()
selectBtn.setImage(UIImage.init(named: "icon_maintai_unselect_big"), for: .normal)
selectBtn.setImage(UIImage.init(named: "icon_maintai_select_big"), for: .selected)
contentView.addSubview(selectBtn)
contentView.bringSubviewToFront(selectBtn)
selectBtn.addTarget(self, action: #selector(selectChange), for: .touchUpInside)
selectBtn.snp.makeConstraints { make in
make.right.bottom.equalToSuperview()
make.size.equalTo(30)
var model:AssetModel?{
didSet{
guard let model = model else{
return
}
coverImage.asset.load(withLocalIdentifier: model.localIdentifier)
}
}
override func layoutSubviews() {
super.layoutSubviews()
coverImage.layer.cornerRadius = 12
coverImage.layer.masksToBounds = true
}
@objc func selectChange(){
selectChangeBlock?()
......
......@@ -11,46 +11,46 @@
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MaintaiDetailImageCell" customModule="PhoneManager" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="196" height="196"/>
<rect key="frame" x="0.0" y="0.0" width="229" height="274"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="196" height="196"/>
<rect key="frame" x="0.0" y="0.0" width="229" height="274"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Rectangle_1543788350" translatesAutoresizingMaskIntoConstraints="NO" id="T4a-zL-UKQ">
<rect key="frame" x="0.0" y="0.0" width="196" height="196"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="12"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<rect key="frame" x="0.0" y="0.0" width="229" height="274"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TpI-ir-4xJ">
<rect key="frame" x="93" y="87.666666666666671" width="10.333333333333329" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oJ5-js-pjw">
<rect key="frame" x="199" y="244" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="gGs-ha-T24"/>
<constraint firstAttribute="height" constant="30" id="mvi-bY-CFY"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="icon_maintai_unselect_big"/>
<state key="selected" image="icon_maintai_select_big"/>
</button>
</subviews>
</view>
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
<constraints>
<constraint firstItem="TpI-ir-4xJ" firstAttribute="centerX" secondItem="gTV-IL-0wX" secondAttribute="centerX" id="0GX-h1-RaA"/>
<constraint firstAttribute="trailing" secondItem="oJ5-js-pjw" secondAttribute="trailing" id="89b-qL-vQ2"/>
<constraint firstAttribute="bottom" secondItem="T4a-zL-UKQ" secondAttribute="bottom" id="B7R-M8-dpU"/>
<constraint firstItem="T4a-zL-UKQ" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="MoV-lR-Hqz"/>
<constraint firstItem="TpI-ir-4xJ" firstAttribute="centerY" secondItem="gTV-IL-0wX" secondAttribute="centerY" id="NdE-xI-xGz"/>
<constraint firstAttribute="bottom" secondItem="oJ5-js-pjw" secondAttribute="bottom" id="Wa8-LG-Qmb"/>
<constraint firstItem="T4a-zL-UKQ" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="dJs-Pa-MhO"/>
<constraint firstAttribute="trailing" secondItem="T4a-zL-UKQ" secondAttribute="trailing" id="gyj-E3-guF"/>
</constraints>
<size key="customSize" width="196" height="196"/>
<size key="customSize" width="229" height="274"/>
<connections>
<outlet property="coverImage" destination="T4a-zL-UKQ" id="jMv-d1-6ah"/>
<outlet property="num" destination="TpI-ir-4xJ" id="Eiw-uk-OeQ"/>
</connections>
<point key="canvasLocation" x="218.32061068702288" y="71.126760563380287"/>
<point key="canvasLocation" x="243.51145038167937" y="98.591549295774655"/>
</collectionViewCell>
</objects>
<resources>
<image name="Rectangle_1543788350" width="222" height="299"/>
<image name="icon_maintai_select_big" width="18" height="18"/>
<image name="icon_maintai_unselect_big" width="18" height="18"/>
</resources>
</document>
......@@ -17,8 +17,21 @@ class MaintaiDetailImageSmallCell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
coverImage.layer.cornerRadius = 12
coverImage.layer.masksToBounds = true
setUI()
}
var model:AssetModel?{
didSet{
guard let model = model else{
return
}
coverImage.asset.load(withLocalIdentifier: model.localIdentifier)
}
}
private func setUI(){
......@@ -26,8 +39,7 @@ class MaintaiDetailImageSmallCell: UICollectionViewCell {
selectBtn = UIButton()
selectBtn.setImage(UIImage.init(named: "icon_maintai_unselect_small"), for: .normal)
selectBtn.setImage(UIImage.init(named: "icon_maintai_select_small"), for: .selected)
contentView.addSubview(selectBtn)
contentView.bringSubviewToFront(selectBtn)
addSubview(selectBtn)
selectBtn.addTarget(self, action: #selector(selectChange), for: .touchUpInside)
selectBtn.snp.makeConstraints { make in
make.right.bottom.equalTo(0)
......
......@@ -13,6 +13,8 @@ class MaintaiDetailPicCell: UITableViewCell {
var selectChangeBlock:(() ->Void)?
@IBOutlet weak var coverImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
setUI()
......@@ -22,8 +24,8 @@ class MaintaiDetailPicCell: UITableViewCell {
selectBtn = UIButton()
selectBtn.setImage(UIImage.init(named: "icon_maintai_unselect_big"), for: .normal)
selectBtn.setImage(UIImage.init(named: "icon_maintai_select_big"), for: .selected)
contentView.addSubview(selectBtn)
contentView.bringSubviewToFront(selectBtn)
selectBtn.backgroundColor = .red
addSubview(selectBtn)
selectBtn.addTarget(self, action: #selector(selectChange), for: .touchUpInside)
selectBtn.snp.makeConstraints { make in
make.right.bottom.equalTo(0)
......@@ -35,4 +37,16 @@ class MaintaiDetailPicCell: UITableViewCell {
selectChangeBlock?()
}
var model:AssetModel?{
didSet{
guard let model = model else{
return
}
coverImage.asset.load(withLocalIdentifier: model.localIdentifier)
}
}
}
......@@ -41,6 +41,9 @@
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="coverImage" destination="P9x-dp-1Do" id="PHu-7r-P0i"/>
</connections>
<point key="canvasLocation" x="479.38931297709922" y="115.49295774647888"/>
</tableViewCell>
</objects>
......
......@@ -28,6 +28,14 @@ class MaintaiDetailTableViewCell: UITableViewCell {
}
var source:[AssetModel] = []{
didSet{
mainCollectionView.reloadData()
pageCollectionView.reloadData()
}
}
func configMain(){
let layout = UICollectionViewFlowLayout()
......@@ -67,16 +75,17 @@ class MaintaiDetailTableViewCell: UITableViewCell {
extension MaintaiDetailTableViewCell:UICollectionViewDelegate,UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
return source.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == mainCollectionView{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MaintaiDetailImageCell", for: indexPath) as! MaintaiDetailImageCell
cell.num.text = "\(indexPath.row)"
cell.model = source[indexPath.row]
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MaintaiDetailImageSmallCell", for: indexPath) as! MaintaiDetailImageSmallCell
cell.model = source[indexPath.row]
return cell
}
......
......@@ -27,6 +27,7 @@ class MaintaiDetialVideoCell: UITableViewCell {
selectBtn = UIButton()
selectBtn.setImage(UIImage.init(named: "icon_maintai_unselect_big"), for: .normal)
selectBtn.setImage(UIImage.init(named: "icon_maintai_select_big"), for: .selected)
selectBtn.backgroundColor = .red
contentView.addSubview(selectBtn)
contentView.bringSubviewToFront(selectBtn)
selectBtn.addTarget(self, action: #selector(selectChange), for: .touchUpInside)
......@@ -49,6 +50,19 @@ class MaintaiDetialVideoCell: UITableViewCell {
playerLayer?.frame = CGRect(x: 0, y: 10, width: contentView.width, height: contentView.height-20)
}
var model:AssetModel?{
didSet{
guard let model = model else{
return
}
PhotoManager.shared.getVideoURL(localIdentifier: model.localIdentifier, completion: {[weak self] url in
guard let weakSelf = self else { return }
weakSelf.configure(with: url)
})
}
}
func configure(with videoURL: URL?) {
guard let videoURL = videoURL else{
player?.pause()
......
//
// MaintaiEmptyView.swift
// PhoneManager
//
// Created by edy on 2025/5/14.
//
import UIKit
class MaintaiEmptyView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="fvO-ix-Gjb" customClass="MaintaiEmptyView" customModule="PhoneManager" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="475" height="328"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_empty_keep" translatesAutoresizingMaskIntoConstraints="NO" id="y21-Z6-DG0">
<rect key="frame" x="114.66666666666669" y="100" width="246" height="169"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="There are no files here." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PFU-dh-epM">
<rect key="frame" x="152.33333333333337" y="289" width="170.66666666666663" height="19.333333333333314"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<viewLayoutGuide key="safeArea" id="u30-FJ-Y4t"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="y21-Z6-DG0" firstAttribute="centerX" secondItem="fvO-ix-Gjb" secondAttribute="centerX" id="6N6-dz-4fq"/>
<constraint firstItem="PFU-dh-epM" firstAttribute="top" secondItem="y21-Z6-DG0" secondAttribute="bottom" constant="20" id="997-iz-9jf"/>
<constraint firstItem="y21-Z6-DG0" firstAttribute="top" secondItem="fvO-ix-Gjb" secondAttribute="top" constant="100" id="JFM-qI-mUN"/>
<constraint firstItem="PFU-dh-epM" firstAttribute="centerX" secondItem="y21-Z6-DG0" secondAttribute="centerX" id="Yvn-Dc-BGy"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="325.95419847328242" y="-101.40845070422536"/>
</view>
</objects>
<resources>
<image name="icon_empty_keep" width="246" height="169"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
......@@ -6,6 +6,8 @@
//
import UIKit
import Kingfisher
import Photos
class MaintainViewListCell: UICollectionViewCell {
......@@ -33,4 +35,31 @@ class MaintainViewListCell: UICollectionViewCell {
selectBlock?()
}
func reloadData(_ asset:[AssetModel],isSelect:Bool){
selectBtn.isSelected = isSelect
if let mediaType = asset.first?.mediaType{
let type = mediaType == 1 ? "Photos" : "Videos"
numberL.text = "\(asset.count)\(type)"
}
if let firstAssetId = asset.first?.localIdentifier{
// PhotoManager.shared.getImage(localIdentifier: firstAssetId) {[weak self] image in
// guard let weakSelf = self else { return }
// if image != nil{
// weakSelf.converImage.image = image
// }
//
// }
// converImage.kf
// let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [firstAssetId], options: nil)
// if let asset = fetchResult.firstObject {
// converImage.kf.setImage(with: asset)
// }
converImage.asset.load(withLocalIdentifier: firstAssetId,placeholder: UIImage.init(named: "othermoren"))
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment