iOS开发针对苹果新系统iOS26的兼容适配UITabBarButtonItem & UITabBar的液态玻璃效果/当前wifi ssid获取

1. UITabBarButtonItem液态玻璃效果

        兼容处理:

        第一种方式(不推荐):把所有的UITabBarButtonItem关闭液态玻璃效果:

 if (@available(iOS 26.0, *)) { self.navigationItem.rightBarButtonItem.hidesSharedBackground = YES; self.navigationItem.leftBarButtonItem.hidesSharedBackground = YES; } else { // Fallback on earlier versions }

        第二种方式:所有导航栏按钮全部采用UITabBarButtonItem,支持液态玻璃效果。

        第三种方式:降低Xcode版本到Xcode25及以下版本,然后再打包

        第四种方式:使用兼容模式显示传统UI风格,也就是取消TabBar液态玻璃效果:

        打开info.plist,添加一个Boolean键值对,取消液态玻璃效果,添加完成后重新运行,UITabBar恢复旧的样式:

<key>UIDesignRequiresCompatibility</key> <true/>

2.  采用UILayoutFittingExpandedSize设置自定义的navigationItem.titleView的内容尺寸,在iOS26上高度偏大,高度变为屏幕的高度,预期是高度应该为导航栏的高度;

原因:在iOS26之前UILayoutFittingExpandedSize最大尺寸限制在导航栏范围内,而在iOS26则允许充斥整个屏幕:

- (CGSize)intrinsicContentSize { return UILayoutFittingExpandedSize; }

        兼容处理:

        修改intrinsicContentSize,指定titleView的尺寸大小为导航栏大小:

 #define SCREEN_WIDTH ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)]?[UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale:[UIScreen mainScreen].bounds.size.width) - (CGSize)intrinsicContentSize { return CGSizeMake(SCREEN_WIDTH, 44); }

3、UITabBarController调用self.setValue(yourTabBar, forKey: "tabBar")自定义tabBar失效

        原因:iOS 26 之后对 UITabBarController 的 KVC 注入限制,导致无效,但不会crash

        兼容处理:

        方案1:使用兼容模式显示传统UI风格,也就是取消TabBar液态玻璃效果:

        打开info.plist,添加一个Boolean键值对,取消液态玻璃效果,添加完成后重新运行,UITabBar恢复旧的样式:

<key>UIDesignRequiresCompatibility</key> <true/>

        方案2:改为使用系统的UITabBarItem组件,能够支持新系统的液态玻璃效果

        方案3:降低Xcode版本到Xcode25及以下版本,然后再打包

4、创建一个由URL标识的代表任何资源的assert对象时报错:

AVAssetExportSessionStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成" UserInfo={ NSUnderlyingError=0x1586626a0 { Error Domain=NSOSStatusErrorDomain Code=-16979 "(null)" }, NSLocalizedFailureReason=发生未知错误(-16979), NSURL=file:///var/mobile/Media/DCIM/100APPLE/IMG_0426.MOV, NSLocalizedDescription=这项操作无法完成 }

        原因:AVAssetExportSession -11800 / -16979 转码失败,权限不足、文件不可读,创建一个由URL标识的代表任何资源的assert对象时,传入的originFilePath示例: file:///var/mobile/Media/DCIM/100APPLE/IMG_0426.MOV,没有读的权限,因为iOS 26对相册视频读取权限收紧,代码示例:

//originFilePath示例: file:///var/mobile/Media/DCIM/100APPLE/IMG_0426.MOV AVURLAsset *asset = [AVURLAsset URLAssetWithURL:originFilePath options:nil]; 

        兼容处理:先将相册的视频拷贝到 App 沙盒临时目录,然后再去创建资源对象AVURLAsset

 [self copyVideoToSandbox:originFilePath completion:^(NSURL *localUrl) { AVURLAsset *asset = [AVURLAsset URLAssetWithURL:localUrl options:nil]; }]; - (void)copyVideoToSandbox:(NSURL *)originUrl completion:(void (^)(NSURL *localUrl))completion { NSString *temp = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tempVideo.mov"]; NSURL *localUrl = [NSURL fileURLWithPath:temp]; NSFileManager *fm = [NSFileManager defaultManager]; if ([fm fileExistsAtPath:temp]) { [fm removeItemAtPath:temp error:nil]; } NSError *err = nil; BOOL ok = [fm copyItemAtURL:originUrl toURL:localUrl error:&err]; if (!ok || err) { NSLog(@"拷贝失败: %@", err); completion(nil); return; } completion(localUrl); } 

5. 通过CNCopySupportedInterfaces获取wifi ssid的方式已失效:

 class func getWifiSSID() -> String? { var wifiName: let wifiInterfaces = CNCopySupportedInterfaces() if wifiInterfaces != nil { let interfaceArr = CFBridgingRetain(wifiInterfaces) as! [String] if interfaceArr.count > 0 { let interfaceName = interfaceArr[0] as CFString let ussafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName) if ussafeInterfaceData != nil { let interfaceData = ussafeInterfaceData as! [String: Any] wifiName = interfaceData["SSID"] as? String ?? "" } else { return nil } } } return wifiName }

        原因:iOS26不再推荐使用CNCopySupportedInterfaces,在iOS26将返回空值

        兼容处理:Capabilities添加Access WiFi Information权限;通过CLLocationManager确保有定位权限,然后使用NEHotspotNetwork获取wifi ssid:

NEHotspotNetwork.fetchCurrent { curNetwork in block(curNetwork?.ssid ?? "") }

Read more

AI时代人人都是产品经理:落地流程:AI 核心功能,从需求到上线的全流程管控方法

AI时代人人都是产品经理:落地流程:AI 核心功能,从需求到上线的全流程管控方法

AI的普及正在重构产品经理的工作模式——不再依赖传统的跨部门协作瓶颈,AI可以成为产品经理的"全职助手",覆盖需求分析、原型设计、开发协同、测试验证全流程。本文将拆解AI时代产品核心功能从0到1落地的完整管控方法,让你用AI能力提升300%的落地效率。 一、需求阶段:AI辅助的需求挖掘与标准化 需求是产品的起点,AI可以帮你从海量信息中精准定位用户真实需求,避免"伪需求"浪费资源。 1. 需求挖掘:AI辅助用户洞察 传统需求调研依赖问卷、访谈,效率低且样本有限。AI可以通过以下方式快速完成用户洞察: * 结构化处理非结构化数据:用AI分析用户在社交媒体、客服对话、应用评论中的碎片化反馈,自动提炼高频需求点 * 需求优先级排序:基于KANO模型,AI可以自动将需求划分为基础型、期望型、兴奋型、无差异型四类,输出优先级列表 实战工具与示例: 使用GPT-4+Python脚本批量处理应用商店评论: import openai import pandas as

人工智能:大模型分布式训练与高效调参技术实战

人工智能:大模型分布式训练与高效调参技术实战

人工智能:大模型分布式训练与高效调参技术实战 1.1 本章学习目标与重点 💡 学习目标:掌握大语言模型分布式训练的核心原理、主流框架使用方法,以及高效调参策略,能够解决大模型训练过程中的算力瓶颈和效果优化问题。 💡 学习重点:理解数据并行、张量并行、流水线并行的技术差异,掌握基于DeepSpeed的分布式训练实战,学会使用超参数搜索提升模型性能。 1.2 大模型训练的核心挑战 1.2.1 单卡训练的算力瓶颈 💡 大语言模型的参数量动辄数十亿甚至上万亿,单张GPU的显存和计算能力完全无法满足训练需求。以LLaMA-2-70B模型为例: * FP32精度下,模型参数本身就需要约280GB显存,远超单张消费级或企业级GPU的显存容量。 * 训练过程中还需要存储梯度、优化器状态等数据,实际显存占用是模型参数的3-4倍。 * 单卡训练的计算速度极慢,训练一轮可能需要数月时间,完全不具备工程可行性。 1.2.2 大模型训练的核心需求 为了高效完成大模型训练,我们需要解决以下三个核心问题: 1. 显存扩容:通过并行技术,将模型参数和计算任务分布到多张GPU上,突破

实测Gemini Pro:谷歌王牌AI,到底能帮我们解决多少实际问题?

实测Gemini Pro:谷歌王牌AI,到底能帮我们解决多少实际问题?

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一、核心亮点实测:不止是“多模态”,更是“真全能” * 1. 多模态处理:能“看、听、读、写”,还能“联动协作” * 2. 推理能力:复杂问题“会拆解、会纠错”,堪比专业助手 * 3. 代码能力:开发者的“全能帮手”,新手也能轻松上手 * 二、真实应用场景:这些领域,已经在用它提效了 * 1. 科研领域:帮研究员“节省时间”,专注核心工作 * 2. 内容创作:

AI写代码工具哪个好用?资深码农实测,看这篇就够!

AI写代码工具哪个好用?资深码农实测,看这篇就够!

身为一个老程序员,我亲身经历了从纯手敲代码到AI智能辅助的演变。现在,如果一个程序员还不懂得利用AI工具,那无异于放弃了“第二次工业革命”。市场上的AI编程工具层出不穷,但究竟哪款才适合你?今天,我就为大家深度评测5款我亲自使用过且认为非常好用的工具,帮你精准避坑,高效提升。 1. Lynx:对话式应用生成器,快速构建原型的神器 Lynx 是一款相对较新但理念非常前沿的对话式AI编程工具。它的目标不仅仅是生成代码片段,而是让你通过自然语言对话,直接创建出可运行的全栈Web应用。 * 核心优势: * 全栈生成: 你只需要用语言描述你想要的应用功能,比如“创建一个带有用户登录和任务列表的待办事项应用”,Lynx 会帮你生成前端、后端和数据库结构,并提供可访问的URL。 * 对话式开发: 整个开发过程就像在与一个资深技术合伙人对话,你可以随时提出修改需求、添加功能,它会实时响应并更新代码。 * 降低门槛: 对于初学者、产品经理或需要快速验证想法的开发者来说,Lynx 能极大地缩短从想法到产品原型的路径。 * 适用场景: 快速构建MVP(最小可行产品)、学习全栈开